• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_context.h"
17 
18 #include <algorithm>
19 
20 #include "display_manager.h"
21 #include "display_info.h"
22 #include "ddm_adapter.h"
23 #include "devicestatus_define.h"
24 #include "dsoftbus_handler.h"
25 #include "utility.h"
26 
27 #undef LOG_TAG
28 #define LOG_TAG "CooperateContext"
29 
30 namespace OHOS {
31 namespace Msdp {
32 namespace DeviceStatus {
33 namespace Cooperate {
34 namespace {
35 const std::string THREAD_NAME { "os_Cooperate_EventHandler" };
36 constexpr double PERCENT { 100.0 };
37 const int32_t MAX_MOUSE_SPEED { 20 };
38 } // namespace
39 
40 class BoardObserver final : public IBoardObserver {
41 public:
BoardObserver(Channel<CooperateEvent>::Sender sender)42     explicit BoardObserver(Channel<CooperateEvent>::Sender sender) : sender_(sender) {}
43     ~BoardObserver() = default;
44     DISALLOW_COPY_AND_MOVE(BoardObserver);
45 
OnBoardOnline(const std::string & networkId)46     void OnBoardOnline(const std::string &networkId) override
47     {
48         FI_HILOGD("\'%{public}s\' is online", Utility::Anonymize(networkId).c_str());
49         auto ret = sender_.Send(CooperateEvent(
50             CooperateEventType::DDM_BOARD_ONLINE,
51             DDMBoardOnlineEvent {
52                 .networkId = networkId
53             }));
54         if (ret != Channel<CooperateEvent>::NO_ERROR) {
55             FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
56         }
57     }
58 
OnBoardOffline(const std::string & networkId)59     void OnBoardOffline(const std::string &networkId) override
60     {
61         FI_HILOGD("\'%{public}s\' is offline", Utility::Anonymize(networkId).c_str());
62         auto ret = sender_.Send(CooperateEvent(
63             CooperateEventType::DDM_BOARD_OFFLINE,
64             DDMBoardOfflineEvent {
65                 .networkId = networkId
66             }));
67         if (ret != Channel<CooperateEvent>::NO_ERROR) {
68             FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
69         }
70     }
71 
72 private:
73     Channel<CooperateEvent>::Sender sender_;
74 };
75 
OnDeviceAdded(std::shared_ptr<IDevice> dev)76 void HotplugObserver::OnDeviceAdded(std::shared_ptr<IDevice> dev)
77 {
78     CHKPV(dev);
79     auto ret = sender_.Send(CooperateEvent(
80         CooperateEventType::INPUT_HOTPLUG_EVENT,
81         InputHotplugEvent {
82             .deviceId = dev->GetId(),
83             .type = InputHotplugType::PLUG,
84             .isKeyboard = dev->IsKeyboard(),
85         }));
86     if (ret != Channel<CooperateEvent>::NO_ERROR) {
87         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
88     }
89 }
90 
OnDeviceRemoved(std::shared_ptr<IDevice> dev)91 void HotplugObserver::OnDeviceRemoved(std::shared_ptr<IDevice> dev)
92 {
93     CHKPV(dev);
94     auto ret = sender_.Send(CooperateEvent(
95         CooperateEventType::INPUT_HOTPLUG_EVENT,
96         InputHotplugEvent {
97             .deviceId = dev->GetId(),
98             .type = InputHotplugType::UNPLUG,
99             .isKeyboard = dev->IsKeyboard(),
100         }));
101     if (ret != Channel<CooperateEvent>::NO_ERROR) {
102         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
103     }
104 }
105 
Context(IContext * env)106 Context::Context(IContext *env)
107     : dsoftbus_(env), eventMgr_(env), hotArea_(env), mouseLocation_(env), inputDevMgr_(env),
108       inputEventBuilder_(env), inputEventInterceptor_(env), env_(env)
109 {}
110 
AttachSender(Channel<CooperateEvent>::Sender sender)111 void Context::AttachSender(Channel<CooperateEvent>::Sender sender)
112 {
113     sender_ = sender;
114     dsoftbus_.AttachSender(sender);
115 }
116 
AddObserver(std::shared_ptr<ICooperateObserver> observer)117 void Context::AddObserver(std::shared_ptr<ICooperateObserver> observer)
118 {
119     CHKPV(observer);
120     observers_.insert(observer);
121 }
122 
RemoveObserver(std::shared_ptr<ICooperateObserver> observer)123 void Context::RemoveObserver(std::shared_ptr<ICooperateObserver> observer)
124 {
125     observers_.erase(observer);
126 }
127 
Enable()128 void Context::Enable()
129 {
130     CALL_DEBUG_ENTER;
131     StartEventHandler();
132     EnableDDM();
133     EnableDevMgr();
134     EnableInputDevMgr();
135 }
136 
Disable()137 void Context::Disable()
138 {
139     CALL_DEBUG_ENTER;
140     DisableDevMgr();
141     DisableDDM();
142     DisableInputDevMgr();
143     StopEventHandler();
144 }
145 
StartEventHandler()146 int32_t Context::StartEventHandler()
147 {
148     auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME, AppExecFwk::ThreadMode::FFRT);
149     CHKPR(runner, RET_ERR);
150     eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
151     return RET_OK;
152 }
153 
StopEventHandler()154 void Context::StopEventHandler()
155 {
156     eventHandler_.reset();
157 }
158 
EnableDDM()159 void Context::EnableDDM()
160 {
161     boardObserver_ = std::make_shared<BoardObserver>(sender_);
162     env_->GetDDM().AddBoardObserver(boardObserver_);
163 }
164 
DisableDDM()165 void Context::DisableDDM()
166 {
167     env_->GetDDM().RemoveBoardObserver(boardObserver_);
168     boardObserver_.reset();
169 }
170 
EnableDevMgr()171 int32_t Context::EnableDevMgr()
172 {
173     hotplugObserver_ = std::make_shared<HotplugObserver>(sender_);
174     env_->GetDeviceManager().AddDeviceObserver(hotplugObserver_);
175     return RET_OK;
176 }
177 
DisableDevMgr()178 void Context::DisableDevMgr()
179 {
180     env_->GetDeviceManager().RemoveDeviceObserver(hotplugObserver_);
181     hotplugObserver_.reset();
182 }
183 
EnableInputDevMgr()184 int32_t Context::EnableInputDevMgr()
185 {
186     inputDevMgr_.Enable(sender_);
187     return RET_OK;
188 }
189 
DisableInputDevMgr()190 void Context::DisableInputDevMgr()
191 {
192     inputDevMgr_.Disable();
193 }
194 
NormalizedCursorPosition() const195 NormalizedCoordinate Context::NormalizedCursorPosition() const
196 {
197     auto display = Rosen::DisplayManager::GetInstance().GetDisplayById(currentDisplayId_);
198     if (display == nullptr) {
199         FI_HILOGE("No default display");
200         return cursorPos_;
201     }
202     Rectangle displayRect {
203         .width = display->GetWidth(),
204         .height = display->GetHeight(),
205     };
206     if ((displayRect.width <= 0) || (displayRect.height <= 0)) {
207         FI_HILOGE("Invalid display information");
208         return cursorPos_;
209     }
210     return NormalizedCoordinate {
211         .x = static_cast<int32_t>((cursorPos_.x + 1) * PERCENT / displayRect.width),
212         .y = static_cast<int32_t>((cursorPos_.y + 1) * PERCENT / displayRect.height),
213     };
214 }
215 
EnableCooperate(const EnableCooperateEvent & event)216 void Context::EnableCooperate(const EnableCooperateEvent &event)
217 {
218 }
219 
DisableCooperate(const DisableCooperateEvent & event)220 void Context::DisableCooperate(const DisableCooperateEvent &event)
221 {
222     priv_ = 0;
223 }
224 
ResetPriv()225 void Context::ResetPriv()
226 {
227     priv_ = 0;
228 }
229 
StartCooperate(const StartCooperateEvent & event)230 void Context::StartCooperate(const StartCooperateEvent &event)
231 {
232     remoteNetworkId_ = event.remoteNetworkId;
233     startDeviceId_ = event.startDeviceId;
234     priv_ = 0;
235 }
236 
OnPointerEvent(const InputPointerEvent & event)237 void Context::OnPointerEvent(const InputPointerEvent &event)
238 {
239     if ((event.sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) &&
240         ((event.pointerAction == MMI::PointerEvent::POINTER_ACTION_MOVE) ||
241          (event.pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE))) {
242         cursorPos_ = event.position;
243         currentDisplayId_ = event.currentDisplayId == -1 ? 0 : event.currentDisplayId;
244     }
245 }
246 
RemoteStartSuccess(const DSoftbusStartCooperateFinished & event)247 void Context::RemoteStartSuccess(const DSoftbusStartCooperateFinished &event)
248 {
249     remoteNetworkId_ = event.originNetworkId;
250     flag_ = event.extra.flag;
251     priv_ = event.extra.priv;
252     SetCursorPosition(event.cursorPos);
253 }
254 
StartCooperateWithOptions(const StartWithOptionsEvent & event)255 void Context::StartCooperateWithOptions(const StartWithOptionsEvent &event)
256 {
257     remoteNetworkId_ = event.remoteNetworkId;
258     startDeviceId_ = event.startDeviceId;
259     priv_ = 0;
260 }
261 
OnRemoteStart(const DSoftbusCooperateWithOptionsFinished & event)262 void Context::OnRemoteStart(const DSoftbusCooperateWithOptionsFinished &event)
263 {
264     remoteNetworkId_ = event.originNetworkId;
265     flag_ = event.extra.flag;
266     priv_ = event.extra.priv;
267     env_->GetInput().SetPointerLocation(event.cooperateOptions.displayX, event.cooperateOptions.displayY,
268         event.cooperateOptions.displayId);
269     FI_HILOGI("Set pointer location: %{private}d, %{private}d, %{private}d",
270         event.cooperateOptions.displayX, event.cooperateOptions.displayY, event.cooperateOptions.displayId);
271 }
272 
RelayCooperate(const DSoftbusRelayCooperate & event)273 void Context::RelayCooperate(const DSoftbusRelayCooperate &event)
274 {
275     remoteNetworkId_ = event.targetNetworkId;
276 }
277 
UpdateCooperateFlag(const UpdateCooperateFlagEvent & event)278 void Context::UpdateCooperateFlag(const UpdateCooperateFlagEvent &event)
279 {
280     flag_ = ((flag_ & ~event.mask) | (event.flag & event.mask));
281 }
282 
IsAllowCooperate()283 bool Context::IsAllowCooperate()
284 {
285     FI_HILOGI("Notify observers of allow cooperate");
286     return std::all_of(observers_.cbegin(), observers_.cend(), [](const auto &observer) {
287         return observer->IsAllowCooperate();
288     });
289 }
290 
OnStartCooperate(StartCooperateData & data)291 void Context::OnStartCooperate(StartCooperateData &data)
292 {
293     std::for_each(observers_.cbegin(), observers_.cend(), [&data](const auto &observer) {
294         return observer->OnStartCooperate(data);
295     });
296 }
297 
OnRemoteStartCooperate(RemoteStartCooperateData & data)298 void Context::OnRemoteStartCooperate(RemoteStartCooperateData &data)
299 {
300     std::for_each(observers_.cbegin(), observers_.cend(), [&data](const auto &observer) {
301         return observer->OnRemoteStartCooperate(data);
302     });
303 }
304 
OnStopCooperate()305 void Context::OnStopCooperate()
306 {
307     CHKPV(eventHandler_);
308     FI_HILOGI("Notify observers of stop cooperate");
309     for (const auto &observer : observers_) {
310         eventHandler_->PostTask(
311             [observer, remoteNetworkId = Peer()] {
312                 FI_HILOGI("Notify observer of stop cooperate");
313                 CHKPV(observer);
314                 observer->OnStopCooperate(remoteNetworkId);
315         });
316     }
317 }
318 
OnTransitionOut()319 void Context::OnTransitionOut()
320 {
321     CHKPV(eventHandler_);
322     FI_HILOGI("Notify observers of transition out");
323     for (const auto &observer : observers_) {
324         eventHandler_->PostTask(
325             [observer, remoteNetworkId = Peer(), cursorPos = NormalizedCursorPosition()] {
326                 FI_HILOGI("Notify one observer of transition out");
327                 CHKPV(observer);
328                 observer->OnTransitionOut(remoteNetworkId, cursorPos);
329             });
330     }
331 }
332 
OnTransitionIn()333 void Context::OnTransitionIn()
334 {
335     StoreOriginPointerSpeed();
336     SetPointerSpeed(peerPointerSpeed_);
337     StoreOriginTouchPadSpeed();
338     SetTouchPadSpeed(peerTouchPadSpeed_);
339     CHKPV(eventHandler_);
340     FI_HILOGI("Notify observers of transition in");
341     for (const auto &observer : observers_) {
342         eventHandler_->PostTask(
343             [observer, remoteNetworkId = Peer(), cursorPos = NormalizedCursorPosition()] {
344                 FI_HILOGI("Notify one observer of transition in");
345                 CHKPV(observer);
346                 observer->OnTransitionIn(remoteNetworkId, cursorPos);
347             });
348     }
349 }
350 
OnBack()351 void Context::OnBack()
352 {
353     SetPointerSpeed(originPointerSpeed_);
354     ClearPeerPointerSpeed();
355     SetTouchPadSpeed(originTouchPadSpeed_);
356     ClearPeerTouchPadSpeed();
357     CHKPV(eventHandler_);
358     FI_HILOGI("Notify observers of come back");
359     for (const auto &observer : observers_) {
360         eventHandler_->PostTask(
361             [observer, remoteNetworkId = Peer(), cursorPos = NormalizedCursorPosition()] {
362                 FI_HILOGI("Notify one observer of come back");
363                 CHKPV(observer);
364                 observer->OnBack(remoteNetworkId, cursorPos);
365             });
366     }
367 }
368 
OnRelayCooperation(const std::string & networkId,const NormalizedCoordinate & cursorPos)369 void Context::OnRelayCooperation(const std::string &networkId, const NormalizedCoordinate &cursorPos)
370 {
371     CHKPV(eventHandler_);
372     FI_HILOGI("Notify observers of relay cooperation");
373     for (const auto &observer : observers_) {
374         eventHandler_->PostTask(
375             [observer, networkId, cursorPos] {
376                 FI_HILOGI("Notify one observer of relay cooperation");
377                 CHKPV(observer);
378                 observer->OnRelay(networkId, cursorPos);
379             });
380     }
381 }
382 
CloseDistributedFileConnection(const std::string & remoteNetworkId)383 void Context::CloseDistributedFileConnection(const std::string &remoteNetworkId)
384 {
385     CHKPV(eventHandler_);
386     FI_HILOGI("Notify observers of device offline");
387     for (const auto &observer : observers_) {
388         eventHandler_->PostTask(
389             [observer, remoteNetworkId] {
390                 FI_HILOGI("Notify one observer of device offline, remoteNetworkId:%{public}s",
391                     Utility::Anonymize(remoteNetworkId).c_str());
392                 CHKPV(observer);
393                 observer->CloseDistributedFileConnection(remoteNetworkId);
394             });
395     }
396 }
397 
StorePeerPointerSpeed(int32_t speed)398 void Context::StorePeerPointerSpeed(int32_t speed)
399 {
400     CALL_INFO_TRACE;
401     peerPointerSpeed_ = speed;
402 }
403 
ClearPeerPointerSpeed()404 void Context::ClearPeerPointerSpeed()
405 {
406     CALL_INFO_TRACE;
407     peerPointerSpeed_ = -1;
408 }
409 
StoreOriginPointerSpeed()410 void Context::StoreOriginPointerSpeed()
411 {
412     CALL_INFO_TRACE;
413     originPointerSpeed_ = GetPointerSpeed();
414 }
415 
StorePeerTouchPadSpeed(int32_t speed)416 void Context::StorePeerTouchPadSpeed(int32_t speed)
417 {
418     CALL_INFO_TRACE;
419     peerTouchPadSpeed_ = speed;
420 }
421 
ClearPeerTouchPadSpeed()422 void Context::ClearPeerTouchPadSpeed()
423 {
424     CALL_INFO_TRACE;
425     peerTouchPadSpeed_ = -1;
426 }
427 
StoreOriginTouchPadSpeed()428 void Context::StoreOriginTouchPadSpeed()
429 {
430     CALL_INFO_TRACE;
431     originTouchPadSpeed_ = GetTouchPadSpeed();
432 }
433 
OnResetCooperation()434 void Context::OnResetCooperation()
435 {
436     SetPointerSpeed(originPointerSpeed_);
437     ClearPeerPointerSpeed();
438     SetTouchPadSpeed(originTouchPadSpeed_);
439     ClearPeerTouchPadSpeed();
440     priv_ = 0;
441     CHKPV(eventHandler_);
442     FI_HILOGI("Notify observers of reset cooperation");
443     for (const auto &observer : observers_) {
444         eventHandler_->PostTask(
445             [observer] {
446                 FI_HILOGI("Notify one observer of reset cooperation");
447                 CHKPV(observer);
448                 observer->OnReset();
449             });
450     }
451 }
452 
SetCursorPosition(const Coordinate & cursorPos)453 void Context::SetCursorPosition(const Coordinate &cursorPos)
454 {
455     auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
456     CHKPV(display);
457     auto cursor = SetCursorPos(cursorPos);
458     cursorPos_ = cursor;
459     env_->GetInput().SetPointerLocation(cursor.x, cursor.y);
460     FI_HILOGI("Set cursor position (%{private}d,%{private}d)(%{private}d,%{private}d)(%{public}d,%{public}d)",
461         cursorPos.x, cursorPos.y, cursor.x, cursor.y, display->GetWidth(), display->GetHeight());
462 }
463 
StopCooperateSetCursorPosition(const Coordinate & cursorPos)464 void Context::StopCooperateSetCursorPosition(const Coordinate &cursorPos)
465 {
466     auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
467     CHKPV(display);
468     int32_t displayId = static_cast<int32_t>(display->GetId());
469     if (displayId < 0) {
470         displayId = 0;
471     }
472     auto cursor = SetCursorPos(cursorPos);
473     env_->GetInput().SetPointerLocation(cursor.x, cursor.y, displayId);
474     FI_HILOGI("Set cursor position (%{private}d,%{private}d)(%{private}d,%{private}d)(%{public}d,%{public}d),"
475         "dafault display id is %{public}d", cursorPos.x, cursorPos.y, cursor.x, cursor.y,
476         display->GetWidth(), display->GetHeight(), displayId);
477 }
478 
SetCursorPos(const Coordinate & cursorPos)479 Coordinate Context::SetCursorPos(const Coordinate &cursorPos)
480 {
481     double xPercent = (PERCENT - std::clamp<double>(cursorPos.x, 0.0, PERCENT)) / PERCENT;
482     double yPercent = std::clamp<double>(cursorPos.y, 0.0, PERCENT) / PERCENT;
483 
484     auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
485     int32_t displayId = static_cast<int32_t>(display->GetId());
486     if (displayId < 0) {
487         displayId = 0;
488     }
489     if (display == nullptr) {
490         FI_HILOGE("No default display");
491         return cursorPos_;
492     }
493     return Coordinate {
494         .x = static_cast<int32_t>(xPercent * display->GetWidth()),
495         .y = static_cast<int32_t>(yPercent * display->GetHeight()),
496     };
497 }
498 
UpdateCursorPosition()499 void Context::UpdateCursorPosition()
500 {
501     env_->GetInput().SetPointerLocation(cursorPos_.x, cursorPos_.y);
502     FI_HILOGI("Update cursor position (%{private}d,%{private}d)", cursorPos_.x, cursorPos_.y);
503 }
504 
GetPointerSpeed()505 int32_t Context::GetPointerSpeed()
506 {
507     int32_t speed { -1 };
508     env_->GetInput().GetPointerSpeed(speed);
509     FI_HILOGI("Current pointer speed:%{public}d", speed);
510     return speed;
511 }
512 
SetPointerSpeed(int32_t speed)513 void Context::SetPointerSpeed(int32_t speed)
514 {
515     env_->GetInput().SetPointerSpeed(speed);
516     FI_HILOGI("Current pointer speed:%{public}d", speed);
517 }
518 
GetTouchPadSpeed()519 int32_t Context::GetTouchPadSpeed()
520 {
521     int32_t speed { -1 };
522     env_->GetInput().GetTouchPadSpeed(speed);
523     FI_HILOGI("Current touchPad speed:%{public}d", speed);
524     return speed;
525 }
526 
SetTouchPadSpeed(int32_t speed)527 void Context::SetTouchPadSpeed(int32_t speed)
528 {
529     if (speed > MAX_MOUSE_SPEED) {
530         FI_HILOGE("speed is :%{public}d", speed);
531         return;
532     }
533     env_->GetInput().SetTouchPadSpeed(speed);
534     FI_HILOGI("Current touchPad speed:%{public}d", speed);
535 }
536 
ResetCursorPosition()537 void Context::ResetCursorPosition()
538 {
539     constexpr Coordinate defaultCursorPos {
540         .x = 50,
541         .y = 50,
542     };
543     StopCooperateSetCursorPosition(defaultCursorPos);
544 }
545 
546 #ifdef ENABLE_PERFORMANCE_CHECK
StartTrace(const std::string & name)547 void Context::StartTrace(const std::string &name)
548 {
549     std::lock_guard guard { lock_ };
550     if (traces_.find(name) != traces_.end()) {
551         return;
552     }
553     traces_.emplace(name, std::chrono::steady_clock::now());
554     FI_HILOGI("[PERF] Start tracing \'%{public}s\'", name.c_str());
555 }
556 
FinishTrace(const std::string & name)557 void Context::FinishTrace(const std::string &name)
558 {
559     std::lock_guard guard { lock_ };
560     if (auto iter = traces_.find(name); iter != traces_.end()) {
561         FI_HILOGI("[PERF] Finish tracing \'%{public}s\', elapsed:%{public}lld ms", name.c_str(),
562             std::chrono::duration_cast<std::chrono::milliseconds>(
563                 std::chrono::steady_clock::now() - iter->second).count());
564         traces_.erase(iter);
565     }
566 }
567 #endif // ENABLE_PERFORMANCE_CHECK
568 
569 } // namespace Cooperate
570 } // namespace DeviceStatus
571 } // namespace Msdp
572 } // namespace OHOS
573