1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "cooperate.h" 17 18#ifdef ENABLE_PERFORMANCE_CHECK 19#include <sstream> 20#include "utility.h" 21#endif // ENABLE_PERFORMANCE_CHECK 22 23#include "devicestatus_define.h" 24 25#undef LOG_TAG 26#define LOG_TAG "Cooperate" 27 28namespace OHOS { 29namespace Msdp { 30namespace DeviceStatus { 31namespace Cooperate { 32 33Cooperate::Cooperate(IContext *env) 34 : env_(env), context_(env), sm_(env) 35{ 36 auto [sender, receiver] = Channel<CooperateEvent>::OpenChannel(); 37 receiver_ = receiver; 38 receiver_.Enable(); 39 context_.AttachSender(sender); 40 context_.Enable(); 41 StartWorker(); 42} 43 44Cooperate::~Cooperate() 45{ 46 StopWorker(); 47 context_.Disable(); 48} 49 50void Cooperate::AddObserver(std::shared_ptr<ICooperateObserver> observer) 51{ 52 CALL_DEBUG_ENTER; 53 auto ret = context_.Sender().Send(CooperateEvent( 54 CooperateEventType::ADD_OBSERVER, 55 AddObserverEvent { 56 .observer = observer 57 })); 58 if (ret != Channel<CooperateEvent>::NO_ERROR) { 59 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 60 } 61} 62 63void Cooperate::RemoveObserver(std::shared_ptr<ICooperateObserver> observer) 64{ 65 CALL_DEBUG_ENTER; 66 auto ret = context_.Sender().Send(CooperateEvent( 67 CooperateEventType::REMOVE_OBSERVER, 68 RemoveObserverEvent { 69 .observer = observer 70 })); 71 if (ret != Channel<CooperateEvent>::NO_ERROR) { 72 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 73 } 74} 75 76int32_t Cooperate::RegisterListener(int32_t pid) 77{ 78 CALL_DEBUG_ENTER; 79 auto ret = context_.Sender().Send(CooperateEvent( 80 CooperateEventType::REGISTER_LISTENER, 81 RegisterListenerEvent { 82 .pid = pid 83 })); 84 if (ret != Channel<CooperateEvent>::NO_ERROR) { 85 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 86 } 87 return RET_OK; 88} 89 90int32_t Cooperate::UnregisterListener(int32_t pid) 91{ 92 CALL_DEBUG_ENTER; 93 auto ret = context_.Sender().Send(CooperateEvent( 94 CooperateEventType::UNREGISTER_LISTENER, 95 UnregisterListenerEvent { 96 .pid = pid 97 })); 98 if (ret != Channel<CooperateEvent>::NO_ERROR) { 99 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 100 } 101 return RET_OK; 102} 103 104int32_t Cooperate::RegisterHotAreaListener(int32_t pid) 105{ 106 CALL_DEBUG_ENTER; 107 auto ret = context_.Sender().Send(CooperateEvent( 108 CooperateEventType::REGISTER_HOTAREA_LISTENER, 109 RegisterHotareaListenerEvent { 110 .pid = pid 111 })); 112 if (ret != Channel<CooperateEvent>::NO_ERROR) { 113 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 114 } 115 return RET_OK; 116} 117 118int32_t Cooperate::UnregisterHotAreaListener(int32_t pid) 119{ 120 CALL_DEBUG_ENTER; 121 auto ret = context_.Sender().Send(CooperateEvent( 122 CooperateEventType::UNREGISTER_HOTAREA_LISTENER, 123 UnregisterHotareaListenerEvent { 124 .pid = pid 125 })); 126 if (ret != Channel<CooperateEvent>::NO_ERROR) { 127 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 128 } 129 return RET_OK; 130} 131 132int32_t Cooperate::Enable(int32_t tokenId, int32_t pid, int32_t userData) 133{ 134 CALL_DEBUG_ENTER; 135 auto ret = context_.Sender().Send(CooperateEvent( 136 CooperateEventType::ENABLE, 137 EnableCooperateEvent { 138 .tokenId = tokenId, 139 .pid = pid, 140 .userData = userData, 141 })); 142 if (ret != Channel<CooperateEvent>::NO_ERROR) { 143 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 144 } 145 return RET_OK; 146} 147 148int32_t Cooperate::Disable(int32_t pid, int32_t userData) 149{ 150 CALL_DEBUG_ENTER; 151 auto ret = context_.Sender().Send(CooperateEvent( 152 CooperateEventType::DISABLE, 153 DisableCooperateEvent { 154 .pid = pid, 155 .userData = userData, 156 })); 157 if (ret != Channel<CooperateEvent>::NO_ERROR) { 158 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 159 } 160 return RET_OK; 161} 162 163int32_t Cooperate::Start(int32_t pid, int32_t userData, const std::string &remoteNetworkId, int32_t startDeviceId) 164{ 165 CALL_DEBUG_ENTER; 166 167#ifdef ENABLE_PERFORMANCE_CHECK 168 std::ostringstream ss; 169 ss << "start_cooperation_with_" << Utility::Anonymize(remoteNetworkId).c_str(); 170 context_.StartTrace(ss.str()); 171#endif // ENABLE_PERFORMANCE_CHECK 172 StartCooperateEvent event { 173 .pid = pid, 174 .userData = userData, 175 .remoteNetworkId = remoteNetworkId, 176 .startDeviceId = startDeviceId, 177 .errCode = std::make_shared<std::promise<int32_t>>(), 178 }; 179 auto errCode = event.errCode->get_future(); 180 auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::START, event)); 181 if (ret != Channel<CooperateEvent>::NO_ERROR) { 182 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 183 } 184 return errCode.get(); 185} 186 187int32_t Cooperate::Stop(int32_t pid, int32_t userData, bool isUnchained) 188{ 189 CALL_DEBUG_ENTER; 190 auto ret = context_.Sender().Send(CooperateEvent( 191 CooperateEventType::STOP, 192 StopCooperateEvent { 193 .pid = pid, 194 .userData = userData, 195 .isUnchained = isUnchained, 196 })); 197 if (ret != Channel<CooperateEvent>::NO_ERROR) { 198 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 199 } 200 return RET_OK; 201} 202 203int32_t Cooperate::GetCooperateState(int32_t pid, int32_t userData, const std::string &networkId) 204{ 205 CALL_DEBUG_ENTER; 206 auto ret = context_.Sender().Send(CooperateEvent( 207 CooperateEventType::GET_COOPERATE_STATE, 208 GetCooperateStateEvent { 209 .pid = pid, 210 .userData = userData, 211 .networkId = networkId, 212 })); 213 if (ret != Channel<CooperateEvent>::NO_ERROR) { 214 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 215 } 216 return RET_OK; 217} 218 219int32_t Cooperate::RegisterEventListener(int32_t pid, const std::string &networkId) 220{ 221 CALL_DEBUG_ENTER; 222 auto ret = context_.Sender().Send(CooperateEvent( 223 CooperateEventType::REGISTER_EVENT_LISTENER, 224 RegisterEventListenerEvent { 225 .pid = pid, 226 .networkId = networkId, 227 })); 228 if (ret != Channel<CooperateEvent>::NO_ERROR) { 229 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 230 } 231 return RET_OK; 232} 233 234int32_t Cooperate::UnregisterEventListener(int32_t pid, const std::string &networkId) 235{ 236 CALL_DEBUG_ENTER; 237 auto ret = context_.Sender().Send(CooperateEvent( 238 CooperateEventType::UNREGISTER_EVENT_LISTENER, 239 UnregisterEventListenerEvent { 240 .pid = pid, 241 .networkId = networkId, 242 })); 243 if (ret != Channel<CooperateEvent>::NO_ERROR) { 244 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 245 } 246 return RET_OK; 247} 248 249int32_t Cooperate::GetCooperateState(const std::string &udId, bool &state) 250{ 251 CALL_DEBUG_ENTER; 252 state = sm_.IsCooperateEnable(); 253 return RET_OK; 254} 255 256int32_t Cooperate::Update(uint32_t mask, uint32_t flag) 257{ 258 auto ret = context_.Sender().Send(CooperateEvent( 259 CooperateEventType::UPDATE_COOPERATE_FLAG, 260 UpdateCooperateFlagEvent { 261 .mask = mask, 262 .flag = flag, 263 })); 264 if (ret != Channel<CooperateEvent>::NO_ERROR) { 265 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 266 } 267 return RET_OK; 268} 269 270int32_t Cooperate::SetDamplingCoefficient(uint32_t direction, double coefficient) 271{ 272 auto ret = context_.Sender().Send(CooperateEvent( 273 CooperateEventType::SET_DAMPLING_COEFFICIENT, 274 SetDamplingCoefficientEvent { 275 .direction = direction, 276 .coefficient = coefficient, 277 })); 278 if (ret != Channel<CooperateEvent>::NO_ERROR) { 279 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 280 } 281 return RET_OK; 282} 283 284void Cooperate::Dump(int32_t fd) 285{ 286 CALL_DEBUG_ENTER; 287 auto ret = context_.Sender().Send(CooperateEvent( 288 CooperateEventType::DUMP, 289 DumpEvent { 290 .fd = fd 291 })); 292 if (ret != Channel<CooperateEvent>::NO_ERROR) { 293 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 294 } 295} 296 297void Cooperate::Loop() 298{ 299 CALL_DEBUG_ENTER; 300 bool running = true; 301 SetThreadName("OS_Cooperate"); 302 LoadMotionDrag(); 303 304 while (running) { 305 CooperateEvent event = receiver_.Receive(); 306 switch (event.type) { 307 case CooperateEventType::NOOP: { 308 break; 309 } 310 case CooperateEventType::QUIT: { 311 FI_HILOGI("Skip out of loop"); 312 running = false; 313 break; 314 } 315 case CooperateEventType::SET_DAMPLING_COEFFICIENT: { 316 SetDamplingCoefficient(event); 317 break; 318 } 319 default: { 320 sm_.OnEvent(context_, event); 321 break; 322 } 323 } 324 } 325} 326 327void Cooperate::StartWorker() 328{ 329 CALL_DEBUG_ENTER; 330 std::lock_guard guard(lock_); 331 if (!workerStarted_) { 332 workerStarted_ = true; 333 worker_ = std::thread([this] { this->Loop(); }); 334 } 335} 336 337void Cooperate::StopWorker() 338{ 339 CALL_DEBUG_ENTER; 340 std::lock_guard guard(lock_); 341 if (workerStarted_) { 342 auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::QUIT)); 343 if (ret != Channel<CooperateEvent>::NO_ERROR) { 344 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret); 345 } 346 if (worker_.joinable()) { 347 worker_.join(); 348 } 349 workerStarted_ = false; 350 } 351} 352 353void Cooperate::LoadMotionDrag() 354{ 355 FI_HILOGI("Load 'MotionDrag' module"); 356 IMotionDrag *motionDrag = env_->GetPluginManager().LoadMotionDrag(); 357 if (motionDrag == nullptr) { 358 FI_HILOGE("Failed to load motion drag"); 359 return; 360 } 361 motionDrag->Enable(context_.EventHandler()); 362} 363 364void Cooperate::SetDamplingCoefficient(const CooperateEvent &event) 365{ 366 SetDamplingCoefficientEvent notice = std::get<SetDamplingCoefficientEvent>(event.event); 367 context_.inputEventBuilder_.SetDamplingCoefficient(notice.direction, notice.coefficient); 368} 369 370extern "C" ICooperate* CreateInstance(IContext *env) 371{ 372 CHKPP(env); 373 return new Cooperate(env); 374} 375 376extern "C" void DestroyInstance(ICooperate *instance) 377{ 378 if (instance != nullptr) { 379 delete instance; 380 } 381} 382} // namespace Cooperate 383} // namespace DeviceStatus 384} // namespace Msdp 385} // namespace OHOS