1 /*
2  * Copyright (c) 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 "mouse_location.h"
17 
18 #include "devicestatus_define.h"
19 #include "dsoftbus_handler.h"
20 #include "utility.h"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "MouseLocation"
24 
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 namespace Cooperate {
29 
MouseLocation(IContext * context)30 MouseLocation::MouseLocation(IContext *context) : context_(context) {}
31 
AddListener(const RegisterEventListenerEvent & event)32 void MouseLocation::AddListener(const RegisterEventListenerEvent &event)
33 {
34     CALL_INFO_TRACE;
35     std::lock_guard<std::mutex> guard(mutex_);
36     localNetworkId_ = IDSoftbusAdapter::GetLocalNetworkId();
37     if (event.networkId == localNetworkId_) {
38         FI_HILOGI("Add local mouse location listener");
39         localListeners_.insert(event.pid);
40         return;
41     }
42     FI_HILOGI("Add remote mouse location listener, networkId:%{public}s", Utility::Anonymize(event.networkId).c_str());
43     DSoftbusSubscribeMouseLocation softbusEvent {
44         .networkId = localNetworkId_,
45         .remoteNetworkId = event.networkId,
46     };
47     SubscribeMouseLocation(softbusEvent);
48     listeners_[event.networkId].insert(event.pid);
49 }
50 
RemoveListener(const UnregisterEventListenerEvent & event)51 void MouseLocation::RemoveListener(const UnregisterEventListenerEvent &event)
52 {
53     CALL_INFO_TRACE;
54     std::lock_guard<std::mutex> guard(mutex_);
55     localNetworkId_ = IDSoftbusAdapter::GetLocalNetworkId();
56     if (event.networkId == localNetworkId_) {
57         FI_HILOGI("Remove local mouse location listener");
58         localListeners_.erase(event.pid);
59         return;
60     }
61     DSoftbusUnSubscribeMouseLocation softbusEvent {
62         .networkId = localNetworkId_,
63         .remoteNetworkId = event.networkId,
64     };
65     UnSubscribeMouseLocation(softbusEvent);
66     if (listeners_.find(event.networkId) != listeners_.end()) {
67         FI_HILOGE("No listener for networkId:%{public}s", Utility::Anonymize(event.networkId).c_str());
68         return;
69     }
70     listeners_[event.networkId].erase(event.pid);
71     if (listeners_[event.networkId].empty()) {
72         listeners_.erase(event.networkId);
73     }
74 }
75 
OnClientDied(const ClientDiedEvent & event)76 void MouseLocation::OnClientDied(const ClientDiedEvent &event)
77 {
78     CALL_INFO_TRACE;
79     std::lock_guard<std::mutex> guard(mutex_);
80     localNetworkId_ = IDSoftbusAdapter::GetLocalNetworkId();
81     FI_HILOGI("Remove client died listener, pid: %{public}d", event.pid);
82     localListeners_.erase(event.pid);
83     for (auto it = listeners_.begin(); it != listeners_.end();) {
84         it->second.erase(event.pid);
85         if (it->second.empty()) {
86             DSoftbusUnSubscribeMouseLocation softbusEvent {
87                 .networkId = localNetworkId_,
88                 .remoteNetworkId = it->first,
89             };
90             UnSubscribeMouseLocation(softbusEvent);
91             it = listeners_.erase(it);
92         } else {
93             ++it;
94         }
95     }
96 }
97 
OnSubscribeMouseLocation(const DSoftbusSubscribeMouseLocation & notice)98 void MouseLocation::OnSubscribeMouseLocation(const DSoftbusSubscribeMouseLocation &notice)
99 {
100     CALL_INFO_TRACE;
101     std::lock_guard<std::mutex> guard(mutex_);
102     CHKPV(context_);
103     remoteSubscribers_.insert(notice.networkId);
104     FI_HILOGI("Add subscriber for networkId:%{public}s successfully", Utility::Anonymize(notice.networkId).c_str());
105     DSoftbusReplySubscribeMouseLocation event = {
106         .networkId = notice.remoteNetworkId,
107         .remoteNetworkId = notice.networkId,
108         .result = true,
109     };
110     FI_HILOGI("ReplySubscribeMouseLocation from networkId:%{public}s to networkId:%{public}s",
111         Utility::Anonymize(event.networkId).c_str(), Utility::Anonymize(event.remoteNetworkId).c_str());
112     ReplySubscribeMouseLocation(event);
113 }
114 
OnUnSubscribeMouseLocation(const DSoftbusUnSubscribeMouseLocation & notice)115 void MouseLocation::OnUnSubscribeMouseLocation(const DSoftbusUnSubscribeMouseLocation &notice)
116 {
117     CALL_INFO_TRACE;
118     std::lock_guard<std::mutex> guard(mutex_);
119     localNetworkId_ = IDSoftbusAdapter::GetLocalNetworkId();
120     if (remoteSubscribers_.find(notice.networkId) == remoteSubscribers_.end()) {
121         FI_HILOGE("No subscriber for networkId:%{public}s stored in remote subscriber",
122             Utility::Anonymize(notice.networkId).c_str());
123         return;
124     }
125     remoteSubscribers_.erase(notice.networkId);
126     DSoftbusReplyUnSubscribeMouseLocation event = {
127         .networkId = notice.remoteNetworkId,
128         .remoteNetworkId = notice.networkId,
129         .result = true,
130     };
131     FI_HILOGI("ReplyUnSubscribeMouseLocation from networkId:%{public}s to networkId:%{public}s",
132         Utility::Anonymize(event.networkId).c_str(), Utility::Anonymize(event.remoteNetworkId).c_str());
133     ReplyUnSubscribeMouseLocation(event);
134 }
135 
OnReplySubscribeMouseLocation(const DSoftbusReplySubscribeMouseLocation & notice)136 void MouseLocation::OnReplySubscribeMouseLocation(const DSoftbusReplySubscribeMouseLocation &notice)
137 {
138     CALL_INFO_TRACE;
139     std::lock_guard<std::mutex> guard(mutex_);
140     if (notice.result) {
141         FI_HILOGI("SubscribeMouseLocation of networkId:%{public}s successfully, localNetworkId:%{public}s",
142             Utility::Anonymize(notice.networkId).c_str(), Utility::Anonymize(notice.remoteNetworkId).c_str());
143     } else {
144         FI_HILOGI("SubscribeMouseLocation of networkId:%{public}s failed, localNetworkId:%{public}s",
145             Utility::Anonymize(notice.networkId).c_str(), Utility::Anonymize(notice.remoteNetworkId).c_str());
146     }
147 }
148 
OnReplyUnSubscribeMouseLocation(const DSoftbusReplyUnSubscribeMouseLocation & notice)149 void MouseLocation::OnReplyUnSubscribeMouseLocation(const DSoftbusReplyUnSubscribeMouseLocation &notice)
150 {
151     CALL_INFO_TRACE;
152     std::lock_guard<std::mutex> guard(mutex_);
153     if (notice.result) {
154         FI_HILOGI("UnSubscribeMouseLocation of networkId:%{public}s successfully, localNetworkId:%{public}s",
155             Utility::Anonymize(notice.networkId).c_str(), Utility::Anonymize(notice.remoteNetworkId).c_str());
156     } else {
157         FI_HILOGI("UnSubscribeMouseLocation of networkId:%{public}s failed, localNetworkId:%{public}s",
158             Utility::Anonymize(notice.networkId).c_str(), Utility::Anonymize(notice.remoteNetworkId).c_str());
159     }
160 }
161 
OnRemoteMouseLocation(const DSoftbusSyncMouseLocation & notice)162 void MouseLocation::OnRemoteMouseLocation(const DSoftbusSyncMouseLocation &notice)
163 {
164     CALL_DEBUG_ENTER;
165     std::lock_guard<std::mutex> guard(mutex_);
166     if (listeners_.find(notice.networkId) == listeners_.end()) {
167         FI_HILOGE("No listener for networkId:%{public}s stored in listeners",
168             Utility::Anonymize(notice.networkId).c_str());
169         return;
170     }
171     LocationInfo locationInfo {
172         .displayX = notice.mouseLocation.displayX,
173         .displayY = notice.mouseLocation.displayY,
174         .displayWidth = notice.mouseLocation.displayWidth,
175         .displayHeight = notice.mouseLocation.displayHeight
176         };
177     for (auto pid : listeners_[notice.networkId]) {
178         ReportMouseLocationToListener(notice.networkId, locationInfo, pid);
179     }
180 }
181 
ProcessData(std::shared_ptr<MMI::PointerEvent> pointerEvent)182 void MouseLocation::ProcessData(std::shared_ptr<MMI::PointerEvent> pointerEvent)
183 {
184     CALL_DEBUG_ENTER;
185     std::lock_guard<std::mutex> guard(mutex_);
186     CHKPV(pointerEvent);
187     if (auto sourceType = pointerEvent->GetSourceType(); sourceType != MMI::PointerEvent::SOURCE_TYPE_MOUSE) {
188         FI_HILOGD("Unexpected sourceType:%{public}d", static_cast<int32_t>(sourceType));
189         return;
190     }
191     LocationInfo locationInfo;
192     TransferToLocationInfo(pointerEvent, locationInfo);
193     if (HasLocalListener()) {
194         for (auto pid : localListeners_) {
195             ReportMouseLocationToListener(localNetworkId_, locationInfo, pid);
196         }
197     }
198     if (!HasRemoteSubscriber()) {
199         FI_HILOGD("No remote subscriber");
200         return;
201     }
202     for (const auto &networkId : remoteSubscribers_) {
203         SyncLocationToRemote(networkId, locationInfo);
204     }
205 }
206 
SyncLocationToRemote(const std::string & remoteNetworkId,const LocationInfo & locationInfo)207 void MouseLocation::SyncLocationToRemote(const std::string &remoteNetworkId, const LocationInfo &locationInfo)
208 {
209     CALL_DEBUG_ENTER;
210     DSoftbusSyncMouseLocation softbusEvent {
211         .networkId = localNetworkId_,
212         .remoteNetworkId = remoteNetworkId,
213         .mouseLocation = {
214             .displayX = locationInfo.displayX,
215             .displayY = locationInfo.displayY,
216             .displayWidth = locationInfo.displayWidth,
217             .displayHeight = locationInfo.displayHeight,
218         },
219     };
220     SyncMouseLocation(softbusEvent);
221 }
222 
ReplySubscribeMouseLocation(const DSoftbusReplySubscribeMouseLocation & event)223 int32_t MouseLocation::ReplySubscribeMouseLocation(const DSoftbusReplySubscribeMouseLocation &event)
224 {
225     CALL_INFO_TRACE;
226     NetPacket packet(MessageId::DSOFTBUS_REPLY_SUBSCRIBE_MOUSE_LOCATION);
227     packet << event.networkId << event.remoteNetworkId << event.result;
228     if (packet.ChkRWError()) {
229         FI_HILOGE("Failed to write data packet");
230         return RET_ERR;
231     }
232     if (SendPacket(event.remoteNetworkId, packet) != RET_OK) {
233         FI_HILOGE("SendPacket failed");
234         return RET_ERR;
235     }
236     return RET_OK;
237 }
238 
ReplyUnSubscribeMouseLocation(const DSoftbusReplyUnSubscribeMouseLocation & event)239 int32_t MouseLocation::ReplyUnSubscribeMouseLocation(const DSoftbusReplyUnSubscribeMouseLocation &event)
240 {
241     CALL_INFO_TRACE;
242     NetPacket packet(MessageId::DSOFTBUS_REPLY_UNSUBSCRIBE_MOUSE_LOCATION);
243     packet << event.networkId << event.remoteNetworkId << event.result;
244     if (packet.ChkRWError()) {
245         FI_HILOGE("Failed to write data packet");
246         return RET_ERR;
247     }
248     if (SendPacket(event.remoteNetworkId, packet) != RET_OK) {
249         FI_HILOGE("SendPacket failed");
250         return RET_ERR;
251     }
252     return RET_OK;
253 }
254 
SubscribeMouseLocation(const DSoftbusSubscribeMouseLocation & event)255 int32_t MouseLocation::SubscribeMouseLocation(const DSoftbusSubscribeMouseLocation &event)
256 {
257     CALL_INFO_TRACE;
258     NetPacket packet(MessageId::DSOFTBUS_SUBSCRIBE_MOUSE_LOCATION);
259     packet << event.networkId << event.remoteNetworkId;
260     if (packet.ChkRWError()) {
261         FI_HILOGE("Failed to write data packet");
262         return RET_ERR;
263     }
264     if (SendPacket(event.remoteNetworkId, packet) != RET_OK) {
265         FI_HILOGE("SendPacket failed");
266         return RET_ERR;
267     }
268     return RET_OK;
269 }
270 
UnSubscribeMouseLocation(const DSoftbusUnSubscribeMouseLocation & event)271 int32_t MouseLocation::UnSubscribeMouseLocation(const DSoftbusUnSubscribeMouseLocation &event)
272 {
273     CALL_INFO_TRACE;
274     NetPacket packet(MessageId::DSOFTBUS_UNSUBSCRIBE_MOUSE_LOCATION);
275     packet << event.networkId << event.remoteNetworkId;
276     if (packet.ChkRWError()) {
277         FI_HILOGE("Failed to write data packet");
278         return RET_ERR;
279     }
280     if (SendPacket(event.remoteNetworkId, packet) != RET_OK) {
281         FI_HILOGE("SendPacket failed");
282         return RET_ERR;
283     }
284     return RET_OK;
285 }
286 
SyncMouseLocation(const DSoftbusSyncMouseLocation & event)287 int32_t MouseLocation::SyncMouseLocation(const DSoftbusSyncMouseLocation &event)
288 {
289     CALL_DEBUG_ENTER;
290     NetPacket packet(MessageId::DSOFTBUS_MOUSE_LOCATION);
291     packet << event.networkId << event.remoteNetworkId << event.mouseLocation.displayX <<
292         event.mouseLocation.displayY << event.mouseLocation.displayWidth << event.mouseLocation.displayHeight;
293     if (packet.ChkRWError()) {
294         FI_HILOGE("Failed to write data packet");
295         return RET_ERR;
296     }
297     if (SendPacket(event.remoteNetworkId, packet) != RET_OK) {
298         FI_HILOGE("SendPacket failed");
299         return RET_ERR;
300     }
301     return RET_OK;
302 }
303 
ReportMouseLocationToListener(const std::string & networkId,const LocationInfo & locationInfo,int32_t pid)304 void MouseLocation::ReportMouseLocationToListener(const std::string &networkId, const LocationInfo &locationInfo,
305     int32_t pid)
306 {
307     CALL_DEBUG_ENTER;
308     CHKPV(context_);
309     auto session = context_->GetSocketSessionManager().FindSessionByPid(pid);
310     CHKPV(session);
311     NetPacket pkt(MessageId::MOUSE_LOCATION_ADD_LISTENER);
312     pkt << networkId << locationInfo.displayX << locationInfo.displayY <<
313         locationInfo.displayWidth << locationInfo.displayHeight;
314     if (pkt.ChkRWError()) {
315         FI_HILOGE("Packet write data failed");
316         return;
317     }
318     if (!session->SendMsg(pkt)) {
319         FI_HILOGE("Sending failed");
320         return;
321     }
322 }
323 
TransferToLocationInfo(std::shared_ptr<MMI::PointerEvent> pointerEvent,LocationInfo & locationInfo)324 void MouseLocation::TransferToLocationInfo(std::shared_ptr<MMI::PointerEvent> pointerEvent, LocationInfo &locationInfo)
325 {
326     CALL_DEBUG_ENTER;
327     CHKPV(pointerEvent);
328     MMI::PointerEvent::PointerItem pointerItem;
329     if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) {
330         FI_HILOGE("Corrupted pointer event");
331         return;
332     }
333     auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
334     CHKPV(display);
335     locationInfo = {
336         .displayX = pointerItem.GetDisplayX(),
337         .displayY = pointerItem.GetDisplayY(),
338         .displayWidth = display->GetWidth(),
339         .displayHeight = display->GetHeight(),
340     };
341 }
342 
HasRemoteSubscriber()343 bool MouseLocation::HasRemoteSubscriber()
344 {
345     CALL_DEBUG_ENTER;
346     return !remoteSubscribers_.empty();
347 }
348 
HasLocalListener()349 bool MouseLocation::HasLocalListener()
350 {
351     CALL_DEBUG_ENTER;
352     return !localListeners_.empty();
353 }
354 
SendPacket(const std::string & remoteNetworkId,NetPacket & packet)355 int32_t MouseLocation::SendPacket(const std::string &remoteNetworkId, NetPacket &packet)
356 {
357     CALL_DEBUG_ENTER;
358     CHKPR(context_, RET_ERR);
359     if (context_->GetDSoftbus().OpenSession(remoteNetworkId) != RET_OK) {
360         FI_HILOGE("Failed to connect to %{public}s", Utility::Anonymize(remoteNetworkId).c_str());
361         return RET_ERR;
362     }
363     if (context_->GetDSoftbus().SendPacket(remoteNetworkId, packet) != RET_OK) {
364         FI_HILOGE("SendPacket failed to %{public}s", Utility::Anonymize(remoteNetworkId).c_str());
365         return RET_ERR;
366     }
367     return RET_OK;
368 }
369 
370 } // namespace Cooperate
371 } // namespace DeviceStatus
372 } // namespace Msdp
373 } // namespace OHOS