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