• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 "cooperate_hisysevent.h"
21 #include "ddm_adapter.h"
22 #include "devicestatus_define.h"
23 #include "dsoftbus_handler.h"
24 #include "utility.h"
25 
26 #undef LOG_TAG
27 #define LOG_TAG "CooperateContext"
28 
29 namespace OHOS {
30 namespace Msdp {
31 namespace DeviceStatus {
32 namespace Cooperate {
33 namespace {
34 const std::string COOPERATE_SWITCH { "currentStatus" };
35 const std::string THREAD_NAME { "os_Cooperate_EventHandler" };
36 constexpr double PERCENT { 100.0 };
37 } // namespace
38 
39 class BoardObserver final : public IBoardObserver {
40 public:
BoardObserver(Channel<CooperateEvent>::Sender sender)41     explicit BoardObserver(Channel<CooperateEvent>::Sender sender) : sender_(sender) { }
42     ~BoardObserver() = default;
43     DISALLOW_COPY_AND_MOVE(BoardObserver);
44 
OnBoardOnline(const std::string & networkId)45     void OnBoardOnline(const std::string &networkId) override
46     {
47         FI_HILOGD("\'%{public}s\' is online", Utility::Anonymize(networkId).c_str());
48         auto ret = sender_.Send(
49             CooperateEvent(CooperateEventType::DDM_BOARD_ONLINE, DDMBoardOnlineEvent { .networkId = networkId }));
50         if (ret != Channel<CooperateEvent>::NO_ERROR) {
51             FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
52         }
53     }
54 
OnBoardOffline(const std::string & networkId)55     void OnBoardOffline(const std::string &networkId) override
56     {
57         FI_HILOGD("\'%{public}s\' is offline", Utility::Anonymize(networkId).c_str());
58         auto ret = sender_.Send(
59             CooperateEvent(CooperateEventType::DDM_BOARD_OFFLINE, DDMBoardOfflineEvent { .networkId = networkId }));
60         if (ret != Channel<CooperateEvent>::NO_ERROR) {
61             FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
62         }
63     }
64 
65 private:
66     Channel<CooperateEvent>::Sender sender_;
67 };
68 
69 class HotplugObserver final : public IDeviceObserver {
70 public:
HotplugObserver(Channel<CooperateEvent>::Sender sender)71     explicit HotplugObserver(Channel<CooperateEvent>::Sender sender) : sender_(sender) { }
72     ~HotplugObserver() = default;
73 
74     void OnDeviceAdded(std::shared_ptr<IDevice> dev) override;
75     void OnDeviceRemoved(std::shared_ptr<IDevice> dev) override;
76 
77 private:
78     Channel<CooperateEvent>::Sender sender_;
79 };
80 
OnDeviceAdded(std::shared_ptr<IDevice> dev)81 void HotplugObserver::OnDeviceAdded(std::shared_ptr<IDevice> dev)
82 {
83     CHKPV(dev);
84     auto ret = sender_.Send(CooperateEvent(CooperateEventType::INPUT_HOTPLUG_EVENT,
85         InputHotplugEvent {
86             .deviceId = dev->GetId(),
87             .type = InputHotplugType::PLUG,
88             .isKeyboard = dev->IsKeyboard(),
89         }));
90     if (ret != Channel<CooperateEvent>::NO_ERROR) {
91         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
92     }
93 }
94 
OnDeviceRemoved(std::shared_ptr<IDevice> dev)95 void HotplugObserver::OnDeviceRemoved(std::shared_ptr<IDevice> dev)
96 {
97     CHKPV(dev);
98     auto ret = sender_.Send(CooperateEvent(CooperateEventType::INPUT_HOTPLUG_EVENT,
99         InputHotplugEvent {
100             .deviceId = dev->GetId(),
101             .type = InputHotplugType::UNPLUG,
102             .isKeyboard = dev->IsKeyboard(),
103         }));
104     if (ret != Channel<CooperateEvent>::NO_ERROR) {
105         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
106     }
107 }
108 
Context(IContext * env)109 Context::Context(IContext *env)
110     : dsoftbus_(env), eventMgr_(env), hotArea_(env), mouseLocation_(env), inputDevMgr_(env), inputEventBuilder_(env),
111       inputEventInterceptor_(env), env_(env)
112 {
113 }
114 
AttachSender(Channel<CooperateEvent>::Sender sender)115 void Context::AttachSender(Channel<CooperateEvent>::Sender sender)
116 {
117     sender_ = sender;
118     dsoftbus_.AttachSender(sender);
119 }
120 
AddObserver(std::shared_ptr<ICooperateObserver> observer)121 void Context::AddObserver(std::shared_ptr<ICooperateObserver> observer)
122 {
123     CHKPV(observer);
124     observers_.insert(observer);
125 }
126 
RemoveObserver(std::shared_ptr<ICooperateObserver> observer)127 void Context::RemoveObserver(std::shared_ptr<ICooperateObserver> observer)
128 {
129     observers_.erase(observer);
130 }
131 
Enable()132 void Context::Enable()
133 {
134     CALL_DEBUG_ENTER;
135     StartEventHandler();
136     EnableDDM();
137     EnableDevMgr();
138     EnableInputDevMgr();
139 }
140 
Disable()141 void Context::Disable()
142 {
143     CALL_DEBUG_ENTER;
144     DisableDevMgr();
145     DisableDDM();
146     DisableInputDevMgr();
147     StopEventHandler();
148 }
149 
StartEventHandler()150 int32_t Context::StartEventHandler()
151 {
152     auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
153     CHKPR(runner, RET_ERR);
154     eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
155     return RET_OK;
156 }
157 
StopEventHandler()158 void Context::StopEventHandler()
159 {
160     eventHandler_.reset();
161 }
162 
EnableDDM()163 int32_t Context::EnableDDM()
164 {
165     boardObserver_ = std::make_shared<BoardObserver>(sender_);
166     ddm_.AddBoardObserver(boardObserver_);
167     return ddm_.Enable();
168 }
169 
DisableDDM()170 void Context::DisableDDM()
171 {
172     ddm_.Disable();
173     ddm_.RemoveBoardObserver(boardObserver_);
174     boardObserver_.reset();
175 }
176 
EnableDevMgr()177 int32_t Context::EnableDevMgr()
178 {
179     hotplugObserver_ = std::make_shared<HotplugObserver>(sender_);
180     env_->GetDeviceManager().AddDeviceObserver(hotplugObserver_);
181     return RET_OK;
182 }
183 
DisableDevMgr()184 void Context::DisableDevMgr()
185 {
186     env_->GetDeviceManager().RemoveDeviceObserver(hotplugObserver_);
187     hotplugObserver_.reset();
188 }
189 
EnableInputDevMgr()190 int32_t Context::EnableInputDevMgr()
191 {
192     inputDevMgr_.Enable();
193     return RET_OK;
194 }
195 
DisableInputDevMgr()196 void Context::DisableInputDevMgr()
197 {
198     inputDevMgr_.Disable();
199 }
200 
NormalizedCursorPosition() const201 NormalizedCoordinate Context::NormalizedCursorPosition() const
202 {
203     auto display = Rosen::DisplayManagerLite::GetInstance().GetDefaultDisplay();
204     if (display == nullptr) {
205         FI_HILOGE("No default display");
206         return cursorPos_;
207     }
208     Rectangle displayRect {
209         .width = display->GetWidth(),
210         .height = display->GetHeight(),
211     };
212     if ((displayRect.width <= 0) || (displayRect.height <= 0)) {
213         FI_HILOGE("Invalid display information");
214         return cursorPos_;
215     }
216     return NormalizedCoordinate {
217         .x = static_cast<int32_t>((cursorPos_.x + 1) * PERCENT / displayRect.width),
218         .y = static_cast<int32_t>((cursorPos_.y + 1) * PERCENT / displayRect.height),
219     };
220 }
221 
EnableCooperate(const EnableCooperateEvent & event)222 void Context::EnableCooperate(const EnableCooperateEvent &event) { }
223 
DisableCooperate(const DisableCooperateEvent & event)224 void Context::DisableCooperate(const DisableCooperateEvent &event) { }
225 
StartCooperate(const StartCooperateEvent & event)226 void Context::StartCooperate(const StartCooperateEvent &event)
227 {
228     remoteNetworkId_ = event.remoteNetworkId;
229     startDeviceId_ = event.startDeviceId;
230 }
231 
OnPointerEvent(const InputPointerEvent & event)232 void Context::OnPointerEvent(const InputPointerEvent &event)
233 {
234     if ((event.sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) &&
235         ((event.pointerAction == MMI::PointerEvent::POINTER_ACTION_MOVE) ||
236             (event.pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE))) {
237         cursorPos_ = event.position;
238     }
239 }
240 
RemoteStartSuccess(const DSoftbusStartCooperateFinished & event)241 void Context::RemoteStartSuccess(const DSoftbusStartCooperateFinished &event)
242 {
243     remoteNetworkId_ = event.originNetworkId;
244     flag_ = event.extra.flag;
245     SetCursorPosition(event.cursorPos);
246 }
247 
RelayCooperate(const DSoftbusRelayCooperate & event)248 void Context::RelayCooperate(const DSoftbusRelayCooperate &event)
249 {
250     remoteNetworkId_ = event.targetNetworkId;
251 }
252 
UpdateCooperateFlag(const UpdateCooperateFlagEvent & event)253 void Context::UpdateCooperateFlag(const UpdateCooperateFlagEvent &event)
254 {
255     flag_ = ((flag_ & ~event.mask) | (event.flag & event.mask));
256 }
257 
IsAllowCooperate()258 bool Context::IsAllowCooperate()
259 {
260     FI_HILOGI("Notify observers of allow cooperate");
261     return std::all_of(observers_.cbegin(), observers_.cend(), [](const auto &observer) {
262         return observer->IsAllowCooperate();
263     });
264 }
265 
OnStartCooperate(StartCooperateData & data)266 void Context::OnStartCooperate(StartCooperateData &data)
267 {
268     std::for_each(observers_.cbegin(), observers_.cend(), [&data](const auto &observer) {
269         return observer->OnStartCooperate(data);
270     });
271 }
272 
OnRemoteStartCooperate(RemoteStartCooperateData & data)273 void Context::OnRemoteStartCooperate(RemoteStartCooperateData &data)
274 {
275     std::for_each(observers_.cbegin(), observers_.cend(), [&data](const auto &observer) {
276         return observer->OnRemoteStartCooperate(data);
277     });
278 }
279 
OnTransitionOut()280 void Context::OnTransitionOut()
281 {
282     CHKPV(eventHandler_);
283     FI_HILOGI("Notify observers of transition out");
284     for (const auto &observer : observers_) {
285         eventHandler_->PostTask([observer, remoteNetworkId = Peer(), cursorPos = NormalizedCursorPosition()] {
286             FI_HILOGI("Notify one observer of transition out");
287             CHKPV(observer);
288             observer->OnTransitionOut(remoteNetworkId, cursorPos);
289         });
290     }
291 }
292 
OnTransitionIn()293 void Context::OnTransitionIn()
294 {
295     CHKPV(eventHandler_);
296     FI_HILOGI("Notify observers of transition in");
297     for (const auto &observer : observers_) {
298         eventHandler_->PostTask([observer, remoteNetworkId = Peer(), cursorPos = NormalizedCursorPosition()] {
299             FI_HILOGI("Notify one observer of transition in");
300             CHKPV(observer);
301             observer->OnTransitionIn(remoteNetworkId, cursorPos);
302         });
303     }
304 }
305 
OnBack()306 void Context::OnBack()
307 {
308     CHKPV(eventHandler_);
309     FI_HILOGI("Notify observers of come back");
310     for (const auto &observer : observers_) {
311         eventHandler_->PostTask([observer, remoteNetworkId = Peer(), cursorPos = NormalizedCursorPosition()] {
312             FI_HILOGI("Notify one observer of come back");
313             CHKPV(observer);
314             observer->OnBack(remoteNetworkId, cursorPos);
315         });
316     }
317 }
318 
OnRelayCooperation(const std::string & networkId,const NormalizedCoordinate & cursorPos)319 void Context::OnRelayCooperation(const std::string &networkId, const NormalizedCoordinate &cursorPos)
320 {
321     CHKPV(eventHandler_);
322     FI_HILOGI("Notify observers of relay cooperation");
323     for (const auto &observer : observers_) {
324         eventHandler_->PostTask([observer, networkId, cursorPos] {
325             FI_HILOGI("Notify one observer of relay cooperation");
326             CHKPV(observer);
327             observer->OnRelay(networkId, cursorPos);
328         });
329     }
330 }
331 
CloseDistributedFileConnection(const std::string & remoteNetworkId)332 void Context::CloseDistributedFileConnection(const std::string &remoteNetworkId)
333 {
334     CHKPV(eventHandler_);
335     FI_HILOGI("Notify observers of device offline");
336     for (const auto &observer : observers_) {
337         eventHandler_->PostTask([observer, remoteNetworkId] {
338             FI_HILOGI("Notify one observer of device offline, remoteNetworkId:%{public}s",
339                 Utility::Anonymize(remoteNetworkId).c_str());
340             CHKPV(observer);
341             observer->CloseDistributedFileConnection(remoteNetworkId);
342         });
343     }
344 }
345 
OnResetCooperation()346 void Context::OnResetCooperation()
347 {
348     CHKPV(eventHandler_);
349     FI_HILOGI("Notify observers of reset cooperation");
350     for (const auto &observer : observers_) {
351         eventHandler_->PostTask([observer] {
352             FI_HILOGI("Notify one observer of reset cooperation");
353             CHKPV(observer);
354             observer->OnReset();
355         });
356     }
357 }
358 
SetCursorPosition(const Coordinate & cursorPos)359 void Context::SetCursorPosition(const Coordinate &cursorPos)
360 {
361     double xPercent = (PERCENT - std::clamp<double>(cursorPos.x, 0.0, PERCENT)) / PERCENT;
362     double yPercent = std::clamp<double>(cursorPos.y, 0.0, PERCENT) / PERCENT;
363 
364     auto display = Rosen::DisplayManagerLite::GetInstance().GetDefaultDisplay();
365     CHKPV(display);
366     cursorPos_.x = static_cast<int32_t>(xPercent * display->GetWidth());
367     cursorPos_.y = static_cast<int32_t>(yPercent * display->GetHeight());
368     env_->GetInput().SetPointerLocation(cursorPos_.x, cursorPos_.y);
369     FI_HILOGI("Set cursor position (%{private}d,%{private}d)(%{private}d,%{private}d)(%{public}d,%{public}d)",
370         cursorPos.x, cursorPos.y, cursorPos_.x, cursorPos_.y, display->GetWidth(), display->GetHeight());
371 }
372 
UpdateCursorPosition()373 void Context::UpdateCursorPosition()
374 {
375     env_->GetInput().SetPointerLocation(cursorPos_.x, cursorPos_.y);
376     FI_HILOGI("Update cursor position (%{private}d,%{private}d)", cursorPos_.x, cursorPos_.y);
377 }
378 
ResetCursorPosition()379 void Context::ResetCursorPosition()
380 {
381     constexpr Coordinate defaultCursorPos {
382         .x = 50,
383         .y = 50,
384     };
385     SetCursorPosition(defaultCursorPos);
386 }
387 
388 #ifdef ENABLE_PERFORMANCE_CHECK
StartTrace(const std::string & name)389 void Context::StartTrace(const std::string &name)
390 {
391     std::lock_guard guard { lock_ };
392     if (traces_.find(name) != traces_.end()) {
393         return;
394     }
395     traces_.emplace(name, std::chrono::steady_clock::now());
396     FI_HILOGI("[PERF] Start tracing \'%{public}s\'", name.c_str());
397 }
398 
FinishTrace(const std::string & name)399 void Context::FinishTrace(const std::string &name)
400 {
401     std::lock_guard guard { lock_ };
402     if (auto iter = traces_.find(name); iter != traces_.end()) {
403         FI_HILOGI("[PERF] Finish tracing \'%{public}s\', elapsed:%{public}lld ms", name.c_str(),
404             std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - iter->second)
405                 .count());
406         traces_.erase(iter);
407     }
408 }
409 #endif // ENABLE_PERFORMANCE_CHECK
410 
411 } // namespace Cooperate
412 } // namespace DeviceStatus
413 } // namespace Msdp
414 } // namespace OHOS
415