1 /*
2  * Copyright (c) 2022-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 "coordination_manager_impl.h"
17 
18 #include "devicestatus_client.h"
19 #include "devicestatus_define.h"
20 #include "include/util.h"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "CoordinationManagerImpl"
24 
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 
RegisterCoordinationListener(CoordinationListenerPtr listener,bool isCompatible)29 int32_t CoordinationManagerImpl::RegisterCoordinationListener(CoordinationListenerPtr listener, bool isCompatible)
30 {
31     CALL_DEBUG_ENTER;
32     CHKPR(listener, RET_ERR);
33     std::lock_guard<std::mutex> guard(mtx_);
34     for (const auto &item : devCoordinationListener_) {
35         if (item == listener) {
36             FI_HILOGW("The listener already exists");
37             return RET_ERR;
38         }
39     }
40     if (!isListeningProcess_) {
41         FI_HILOGI("Start monitoring");
42         int32_t ret = DeviceStatusClient::GetInstance().RegisterCoordinationListener(isCompatible);
43         if (ret != RET_OK) {
44             FI_HILOGE("Failed to register, ret:%{public}d", ret);
45             return ret;
46         }
47         isListeningProcess_ = true;
48     }
49     devCoordinationListener_.push_back(listener);
50     return RET_OK;
51 }
52 
UnregisterCoordinationListener(CoordinationListenerPtr listener,bool isCompatible)53 int32_t CoordinationManagerImpl::UnregisterCoordinationListener(
54     CoordinationListenerPtr listener, bool isCompatible)
55 {
56     CALL_DEBUG_ENTER;
57     std::lock_guard<std::mutex> guard(mtx_);
58     if (listener == nullptr) {
59         devCoordinationListener_.clear();
60         goto LISTENER_LABEL;
61     }
62     for (auto it = devCoordinationListener_.begin(); it != devCoordinationListener_.end(); ++it) {
63         if (*it == listener) {
64             devCoordinationListener_.erase(it);
65             goto LISTENER_LABEL;
66         }
67     }
68 
69 LISTENER_LABEL:
70     if (isListeningProcess_ && devCoordinationListener_.empty()) {
71         isListeningProcess_ = false;
72         return DeviceStatusClient::GetInstance().UnregisterCoordinationListener(isCompatible);
73     }
74     return RET_OK;
75 }
76 
PrepareCoordination(FuncCoordinationMessage callback,bool isCompatible)77 int32_t CoordinationManagerImpl::PrepareCoordination(FuncCoordinationMessage callback, bool isCompatible)
78 {
79     CALL_DEBUG_ENTER;
80     std::lock_guard<std::mutex> guard(mtx_);
81     prepareCooCallback_ = callback;
82     isPrepareCooIsCompatible_ = isCompatible;
83     SetMessageCallback(CallbackMessageId::PREPARE, callback);
84     int32_t userData = static_cast<int32_t> (CallbackMessageId::PREPARE);
85     int32_t ret = DeviceStatusClient::GetInstance().PrepareCoordination(userData, isCompatible);
86     if (ret != RET_OK) {
87         FI_HILOGE("Prepare coordination failed");
88         return ret;
89     }
90     return RET_OK;
91 }
92 
UnprepareCoordination(FuncCoordinationMessage callback,bool isCompatible)93 int32_t CoordinationManagerImpl::UnprepareCoordination(FuncCoordinationMessage callback, bool isCompatible)
94 {
95     CALL_DEBUG_ENTER;
96     std::lock_guard<std::mutex> guard(mtx_);
97     SetMessageCallback(CallbackMessageId::UNPREPARE, callback);
98     int32_t userData = static_cast<int32_t> (CallbackMessageId::UNPREPARE);
99     int32_t ret = DeviceStatusClient::GetInstance().UnprepareCoordination(userData, isCompatible);
100     if (ret != RET_OK) {
101         FI_HILOGE("Unprepare coordination failed");
102         return ret;
103     }
104     return RET_OK;
105 }
106 
ActivateCoordination(const std::string & remoteNetworkId,int32_t startDeviceId,FuncCoordinationMessage callback,bool isCompatible)107 int32_t CoordinationManagerImpl::ActivateCoordination(const std::string &remoteNetworkId,
108     int32_t startDeviceId, FuncCoordinationMessage callback, bool isCompatible)
109 {
110     CALL_DEBUG_ENTER;
111     std::lock_guard<std::mutex> guard(mtx_);
112     SetMessageCallback(CallbackMessageId::ACTIVATE, callback);
113     int32_t userData = static_cast<int32_t> (CallbackMessageId::ACTIVATE);
114     int32_t ret = DeviceStatusClient::GetInstance().ActivateCoordination(
115         userData, remoteNetworkId, startDeviceId, isCompatible);
116     if (ret != RET_OK) {
117         FI_HILOGE("Activate coordination failed");
118         return ret;
119     }
120     return RET_OK;
121 }
122 
DeactivateCoordination(bool isUnchained,FuncCoordinationMessage callback,bool isCompatible)123 int32_t CoordinationManagerImpl::DeactivateCoordination(bool isUnchained, FuncCoordinationMessage callback,
124     bool isCompatible)
125 {
126     CALL_DEBUG_ENTER;
127     std::lock_guard<std::mutex> guard(mtx_);
128     SetMessageCallback(CallbackMessageId::DEACTIVATE, callback);
129     int32_t userData = static_cast<int32_t> (CallbackMessageId::DEACTIVATE);
130     int32_t ret = DeviceStatusClient::GetInstance().DeactivateCoordination(userData, isUnchained, isCompatible);
131     if (ret != RET_OK) {
132         FI_HILOGE("Deactivate coordination failed");
133         return ret;
134     }
135     return RET_OK;
136 }
137 
GetCoordinationState(const std::string & networkId,FuncCoordinationState callback,bool isCompatible)138 int32_t CoordinationManagerImpl::GetCoordinationState(
139     const std::string &networkId, FuncCoordinationState callback, bool isCompatible)
140 {
141     CALL_DEBUG_ENTER;
142     std::lock_guard<std::mutex> guard(mtx_);
143     SetStateCallback(CallbackMessageId::GET_COORDINATION, callback);
144     int32_t userData = static_cast<int32_t> (CallbackMessageId::GET_COORDINATION);
145     int32_t ret = DeviceStatusClient::GetInstance().GetCoordinationState(userData, networkId, isCompatible);
146     if (ret != RET_OK) {
147         FI_HILOGE("Get coordination state failed, ret:%{public}d", ret);
148         return ret;
149     }
150     return RET_OK;
151 }
152 
GetCoordinationState(const std::string & udId,bool & state)153 int32_t CoordinationManagerImpl::GetCoordinationState(const std::string &udId, bool &state)
154 {
155     CALL_DEBUG_ENTER;
156     std::lock_guard<std::mutex> guard(mtx_);
157     int32_t ret = DeviceStatusClient::GetInstance().GetCoordinationState(udId, state);
158     if (ret != RET_OK) {
159         FI_HILOGE("Get coordination state failed, ret:%{public}d", ret);
160         return ret;
161     }
162     return RET_OK;
163 }
164 
OnDevCoordinationListener(const std::string networkId,CoordinationMessage msg)165 void CoordinationManagerImpl::OnDevCoordinationListener(const std::string networkId, CoordinationMessage msg)
166 {
167     CALL_DEBUG_ENTER;
168     std::lock_guard<std::mutex> guard(mtx_);
169     for (const auto &item : devCoordinationListener_) {
170         item->OnCoordinationMessage(networkId, msg);
171     }
172 }
173 
OnCoordinationMessageEvent(int32_t userData,const std::string networkId,CoordinationMessage msg)174 void CoordinationManagerImpl::OnCoordinationMessageEvent(int32_t userData,
175     const std::string networkId, CoordinationMessage msg)
176 {
177     CALL_DEBUG_ENTER;
178     CHK_PID_AND_TID();
179     std::lock_guard<std::mutex> guard(mtx_);
180     if (devCoordinationEvent_.find(userData) == devCoordinationEvent_.end()) {
181         FI_HILOGE("No callback for CallbackMessageId:%{public}d", userData);
182         return;
183     }
184     CoordinationMsg event = devCoordinationEvent_[userData].msg;
185     CHKPV(event);
186     event(networkId, msg);
187     FI_HILOGD("Coordination msg event callback, userData:%{public}d, networkId:%{public}s",
188         userData, GetAnonyString(networkId).c_str());
189 }
190 
OnCoordinationStateEvent(int32_t userData,bool state)191 void CoordinationManagerImpl::OnCoordinationStateEvent(int32_t userData, bool state)
192 {
193     CALL_DEBUG_ENTER;
194     CHK_PID_AND_TID();
195     std::lock_guard<std::mutex> guard(mtx_);
196     if (devCoordinationEvent_.find(userData) == devCoordinationEvent_.end()) {
197         FI_HILOGE("No callback for CallbackMessageId:%{public}d", userData);
198         return;
199     }
200     CoordinationState event = devCoordinationEvent_[userData].state;
201     CHKPV(event);
202     event(state);
203     FI_HILOGD("Coordination state event callback, userData:%{public}d", userData);
204 }
205 
SetMessageCallback(CallbackMessageId id,FuncCoordinationMessage callback)206 void CoordinationManagerImpl::SetMessageCallback(CallbackMessageId id, FuncCoordinationMessage callback)
207 {
208     CoordinationEvent event;
209     event.msg = callback;
210     devCoordinationEvent_[static_cast<int32_t>(id)] = event;
211     FI_HILOGD("SetMessageCallback for CallbackMessageId:%{public}d", id);
212 }
213 
SetStateCallback(CallbackMessageId id,FuncCoordinationState callback)214 void CoordinationManagerImpl::SetStateCallback(CallbackMessageId id, FuncCoordinationState callback)
215 {
216     CoordinationEvent event;
217     event.state = callback;
218     devCoordinationEvent_[static_cast<int32_t>(id)] = event;
219     FI_HILOGD("SetStateCallback for CallbackMessageId:%{public}d", id);
220 }
221 
OnCoordinationListener(const StreamClient & client,NetPacket & pkt)222 int32_t CoordinationManagerImpl::OnCoordinationListener(const StreamClient &client, NetPacket &pkt)
223 {
224     CALL_DEBUG_ENTER;
225     int32_t userData = 0;
226     std::string networkId;
227     int32_t nType = 0;
228     pkt >> userData >> networkId >> nType;
229     if (pkt.ChkRWError()) {
230         FI_HILOGE("Packet read type failed");
231         return RET_ERR;
232     }
233     FI_HILOGI("UserData:%{public}d, networkId:%{public}s, nType:%{public}d",
234         userData, GetAnonyString(networkId).c_str(), nType);
235     OnDevCoordinationListener(networkId, CoordinationMessage(nType));
236     return RET_OK;
237 }
238 
OnCoordinationMessage(const StreamClient & client,NetPacket & pkt)239 int32_t CoordinationManagerImpl::OnCoordinationMessage(const StreamClient &client, NetPacket &pkt)
240 {
241     CALL_DEBUG_ENTER;
242     int32_t userData = 0;
243     std::string networkId;
244     int32_t nType = 0;
245     pkt >> userData >> networkId >> nType;
246     if (pkt.ChkRWError()) {
247         FI_HILOGE("Packet read coordination msg failed");
248         return RET_ERR;
249     }
250     FI_HILOGI("UserData:%{public}d, networkId:%{public}s, nType:%{public}d",
251         userData, GetAnonyString(networkId).c_str(), nType);
252     OnCoordinationMessageEvent(userData, networkId, CoordinationMessage(nType));
253     return RET_OK;
254 }
255 
OnCoordinationState(const StreamClient & client,NetPacket & pkt)256 int32_t CoordinationManagerImpl::OnCoordinationState(const StreamClient &client, NetPacket &pkt)
257 {
258     CALL_DEBUG_ENTER;
259     int32_t userData = 0;
260     bool state = false;
261     pkt >> userData >> state;
262     if (pkt.ChkRWError()) {
263         FI_HILOGE("Packet read coordination msg failed");
264         return RET_ERR;
265     }
266     FI_HILOGI("UserData:%{public}d, state:%{public}s", userData, (state ? "true" : "false"));
267     OnCoordinationStateEvent(userData, state);
268     return RET_OK;
269 }
270 
AddHotAreaListener(HotAreaListenerPtr listener)271 int32_t CoordinationManagerImpl::AddHotAreaListener(HotAreaListenerPtr listener)
272 {
273     CALL_DEBUG_ENTER;
274     CHKPR(listener, RET_ERR);
275     std::lock_guard<std::mutex> guard(mtx_);
276     for (const auto &item : devHotAreaListener_) {
277         if (item == listener) {
278             FI_HILOGW("The listener already exists");
279             return RET_ERR;
280         }
281     }
282     if (!isHotAreaListener_) {
283         FI_HILOGI("Start monitoring");
284         int32_t ret = DeviceStatusClient::GetInstance().AddHotAreaListener();
285         if (ret != RET_OK) {
286             FI_HILOGE("Failed to add hot area listener, ret:%{public}d", ret);
287             return ret;
288         }
289         isHotAreaListener_ = true;
290     }
291     devHotAreaListener_.push_back(listener);
292     return RET_OK;
293 }
294 
OnDevHotAreaListener(int32_t displayX,int32_t displayY,HotAreaType type,bool isEdge)295 void CoordinationManagerImpl::OnDevHotAreaListener(int32_t displayX,
296     int32_t displayY, HotAreaType type, bool isEdge)
297 {
298     CALL_DEBUG_ENTER;
299     std::lock_guard<std::mutex> guard(mtx_);
300     for (const auto &item : devHotAreaListener_) {
301         item->OnHotAreaMessage(displayX, displayY, type, isEdge);
302     }
303 }
304 
OnHotAreaListener(const StreamClient & client,NetPacket & pkt)305 int32_t CoordinationManagerImpl::OnHotAreaListener(const StreamClient &client, NetPacket &pkt)
306 {
307     CALL_DEBUG_ENTER;
308     int32_t positionX = 0;
309     int32_t positionY = 0;
310     int32_t type = 0;
311     bool isEdge = false;
312     pkt >> positionX >> positionY >> type >> isEdge;
313     if (pkt.ChkRWError()) {
314         FI_HILOGE("Packet read type failed");
315         return RET_ERR;
316     }
317     OnDevHotAreaListener(positionX, positionY, HotAreaType(type), isEdge);
318     return RET_OK;
319 }
320 
RemoveHotAreaListener(HotAreaListenerPtr listener)321 int32_t CoordinationManagerImpl::RemoveHotAreaListener(HotAreaListenerPtr listener)
322 {
323     CALL_DEBUG_ENTER;
324     std::lock_guard<std::mutex> guard(mtx_);
325     if (listener == nullptr) {
326         devHotAreaListener_.clear();
327     } else {
328         devHotAreaListener_.erase(std::remove_if(devHotAreaListener_.begin(), devHotAreaListener_.end(),
329             [listener] (auto items) {
330                 return items == listener;
331             })
332         );
333     }
334 
335     if (isHotAreaListener_ && devHotAreaListener_.empty()) {
336         isHotAreaListener_ = false;
337         return DeviceStatusClient::GetInstance().RemoveHotAreaListener();
338     }
339     return RET_OK;
340 }
341 
OnConnected()342 void CoordinationManagerImpl::OnConnected()
343 {
344     CALL_INFO_TRACE;
345     CHKPV(prepareCooCallback_);
346     if (PrepareCoordination(prepareCooCallback_, isPrepareCooIsCompatible_) != RET_OK) {
347         FI_HILOGE("PrepareCoordination failed");
348     }
349 }
350 
351 } // namespace DeviceStatus
352 } // namespace Msdp
353 } // namespace OHOS