• 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 "fusion_device_profile_adapter.h"
17 
18 #include <set>
19 
20 #include "distributed_device_profile_client.h"
21 #include "singleton.h"
22 
23 #include "devicestatus_define.h"
24 #include "json_parser.h"
25 
26 using namespace OHOS;
27 using namespace OHOS::DeviceProfile;
28 
29 namespace {
30 constexpr HiviewDFX::HiLogLabel LABEL { LOG_CORE, OHOS::Msdp::MSDP_DOMAIN_ID, "FusionDeviceProfile" };
31 const std::string SERVICE_ID { "deviceStatus" };
32 } // namespace
33 
34 class ProfileEventCallback final : public IProfileEventCallback {
35 public:
36     explicit ProfileEventCallback(CICrossStateListener* listener);
37     ~ProfileEventCallback();
38 
39     void OnSyncCompleted(const SyncResult &syncResults) override;
40     void OnProfileChanged(const ProfileChangeNotification &changeNotification) override;
41     bool SupportProfileEvent(const ProfileEvent &event) const;
42     void AddProfileEvent(const ProfileEvent &event);
43     void RemoveProfileEvents(const std::list<ProfileEvent> &profileEvents);
44 
HasProfileEvent() const45     bool HasProfileEvent() const
46     {
47         return !profileEvents_.empty();
48     }
49 
50 private:
51     CICrossStateListener* listener_ { nullptr };
52     std::set<ProfileEvent> profileEvents_;
53 };
54 
55 class FusionDeviceProfileAdapter {
56     DECLARE_DELAYED_REF_SINGLETON(FusionDeviceProfileAdapter);
57 
58 public:
59     int32_t UpdateCrossSwitchState(bool switchState);
60     int32_t SyncCrossSwitchState(bool switchState, const std::vector<std::string> &deviceIds);
61     bool GetCrossSwitchState(const std::string &deviceId);
62     int32_t RegisterCrossStateListener(const std::string &deviceId,
63         const std::shared_ptr<ProfileEventCallback> &callback);
64     int32_t UnregisterCrossStateListener(const std::string &deviceId);
65 
66 private:
67     void SaveSubscribeInfos(const std::string &deviceId,
68                             const std::shared_ptr<ProfileEventCallback> &callback,
69                             std::list<SubscribeInfo> &subscribeInfos);
70     void RemoveFailedSubscriptions(const std::string &deviceId, const std::list<ProfileEvent> &failedEvents);
71 
72 private:
73     std::map<std::string, std::shared_ptr<ProfileEventCallback>> callbacks_;
74     const std::string characteristicsName_ = "currentStatus";
75 };
76 
ProfileEventCallback(CICrossStateListener * listener)77 ProfileEventCallback::ProfileEventCallback(CICrossStateListener* listener)
78 {
79     if ((listener != nullptr) && (listener->clone != nullptr)) {
80         listener_ = listener->clone(listener);
81     }
82 }
83 
~ProfileEventCallback()84 ProfileEventCallback::~ProfileEventCallback()
85 {
86     if ((listener_ != nullptr) && (listener_->destruct != nullptr)) {
87         listener_->destruct(listener_);
88     }
89 }
90 
OnSyncCompleted(const SyncResult & syncResults)91 void ProfileEventCallback::OnSyncCompleted(const SyncResult &syncResults)
92 {
93     std::for_each(syncResults.begin(), syncResults.end(), [](const auto &syncResult) {
94         FI_HILOGD("Sync result:%{public}d", syncResult.second);
95     });
96 }
97 
OnProfileChanged(const ProfileChangeNotification & changeNotification)98 void ProfileEventCallback::OnProfileChanged(const ProfileChangeNotification &changeNotification)
99 {
100     CALL_INFO_TRACE;
101     if (listener_ == nullptr || listener_->onUpdate == nullptr) {
102         FI_HILOGE("listener_ is nullptr or onUpdate is nullptr");
103         return;
104     }
105     std::string deviceId = changeNotification.GetDeviceId();
106     bool switchState = DelayedRefSingleton<FusionDeviceProfileAdapter>::GetInstance().GetCrossSwitchState(deviceId);
107     listener_->onUpdate(listener_, deviceId.c_str(), switchState);
108 }
109 
SupportProfileEvent(const ProfileEvent & event) const110 bool ProfileEventCallback::SupportProfileEvent(const ProfileEvent &event) const
111 {
112     return (profileEvents_.find(event) != profileEvents_.cend());
113 }
114 
AddProfileEvent(const ProfileEvent & event)115 void ProfileEventCallback::AddProfileEvent(const ProfileEvent &event)
116 {
117     auto ret = profileEvents_.insert(event);
118     if (!ret.second) {
119         FI_HILOGW("Profile event is duplicate");
120     }
121 }
122 
RemoveProfileEvents(const std::list<ProfileEvent> & profileEvents)123 void ProfileEventCallback::RemoveProfileEvents(const std::list<ProfileEvent> &profileEvents)
124 {
125     for (const auto &event : profileEvents) {
126         profileEvents_.erase(event);
127     }
128 }
129 
FusionDeviceProfileAdapter()130 FusionDeviceProfileAdapter::FusionDeviceProfileAdapter()
131 {}
132 
~FusionDeviceProfileAdapter()133 FusionDeviceProfileAdapter::~FusionDeviceProfileAdapter()
134 {}
135 
UpdateCrossSwitchState(bool switchState)136 int32_t FusionDeviceProfileAdapter::UpdateCrossSwitchState(bool switchState)
137 {
138     CALL_DEBUG_ENTER;
139     const std::string SERVICE_TYPE = "deviceStatus";
140     ServiceCharacteristicProfile profile;
141     profile.SetServiceId(SERVICE_ID);
142     profile.SetServiceType(SERVICE_TYPE);
143     cJSON* data = cJSON_CreateObject();
144     CHKPR(data, RET_ERR);
145     cJSON_AddItemToObject(data, characteristicsName_.c_str(), cJSON_CreateNumber(switchState));
146     char* smsg = cJSON_Print(data);
147     cJSON_Delete(data);
148     CHKPR(smsg, RET_ERR);
149     profile.SetCharacteristicProfileJson(smsg);
150     cJSON_free(smsg);
151     return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
152 }
153 
SyncCrossSwitchState(bool switchState,const std::vector<std::string> & deviceIds)154 int32_t FusionDeviceProfileAdapter::SyncCrossSwitchState(bool switchState, const std::vector<std::string> &deviceIds)
155 {
156     CALL_DEBUG_ENTER;
157     const std::string SERVICE_TYPE = "deviceStatus";
158     ServiceCharacteristicProfile profile;
159     profile.SetServiceId(SERVICE_ID);
160     profile.SetServiceType(SERVICE_TYPE);
161     cJSON* data = cJSON_CreateObject();
162     CHKPR(data, RET_ERR);
163     cJSON_AddItemToObject(data, characteristicsName_.c_str(), cJSON_CreateNumber(switchState));
164     char* smsg = cJSON_Print(data);
165     cJSON_Delete(data);
166     CHKPR(smsg, RET_ERR);
167     profile.SetCharacteristicProfileJson(smsg);
168     cJSON_free(smsg);
169 
170     int32_t ret = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
171     if (ret != 0) {
172         FI_HILOGE("Put device profile failed, ret:%{public}d", ret);
173         return ret;
174     }
175     SyncOptions syncOptions;
176     std::for_each(deviceIds.begin(), deviceIds.end(),
177                   [&syncOptions](auto &deviceId) {
178                       syncOptions.AddDevice(deviceId);
179                       FI_HILOGD("Add device success");
180                   });
181     auto syncCallback = std::make_shared<ProfileEventCallback>(nullptr);
182     ret = DistributedDeviceProfileClient::GetInstance().SyncDeviceProfile(syncOptions, syncCallback);
183     if (ret != 0) {
184         FI_HILOGE("Sync device profile failed");
185     }
186     return ret;
187 }
188 
GetCrossSwitchState(const std::string & deviceId)189 bool FusionDeviceProfileAdapter::GetCrossSwitchState(const std::string &deviceId)
190 {
191     CALL_DEBUG_ENTER;
192     ServiceCharacteristicProfile profile;
193 
194     DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(deviceId, SERVICE_ID, profile);
195     std::string jsonData = profile.GetCharacteristicProfileJson();
196     JsonParser parser;
197     parser.json = cJSON_Parse(jsonData.c_str());
198     if (!cJSON_IsObject(parser.json)) {
199         FI_HILOGE("parser json is not object");
200         return false;
201     }
202     cJSON* state = cJSON_GetObjectItemCaseSensitive(parser.json, characteristicsName_.c_str());
203     if (!cJSON_IsNumber(state)) {
204         FI_HILOGE("State is not number type");
205         return false;
206     }
207     return (static_cast<bool>(state->valueint));
208 }
209 
RegisterCrossStateListener(const std::string & deviceId,const std::shared_ptr<ProfileEventCallback> & callback)210 int32_t FusionDeviceProfileAdapter::RegisterCrossStateListener(const std::string &deviceId,
211     const std::shared_ptr<ProfileEventCallback> &callback)
212 {
213     CALL_DEBUG_ENTER;
214     CHKPR(callback, RET_ERR);
215     std::list<std::string> serviceIds;
216     serviceIds.emplace_back(SERVICE_ID);
217 
218     ExtraInfo extraInfo;
219     extraInfo["deviceId"] = deviceId;
220     extraInfo["serviceIds"] = serviceIds;
221 
222     SubscribeInfo changeEventInfo;
223     changeEventInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
224     changeEventInfo.extraInfo = std::move(extraInfo);
225 
226     std::list<SubscribeInfo> subscribeInfos;
227     subscribeInfos.emplace_back(changeEventInfo);
228 
229     SubscribeInfo syncEventInfo;
230     syncEventInfo.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED;
231     subscribeInfos.emplace_back(syncEventInfo);
232 
233     SaveSubscribeInfos(deviceId, callback, subscribeInfos);
234 
235     if (subscribeInfos.empty()) {
236         FI_HILOGI("Profile events have been subscribed");
237         return RET_ERR;
238     }
239 
240     std::list<ProfileEvent> failedEvents;
241     return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(
242         subscribeInfos, callback, failedEvents);
243 }
244 
UnregisterCrossStateListener(const std::string & deviceId)245 int32_t FusionDeviceProfileAdapter::UnregisterCrossStateListener(const std::string &deviceId)
246 {
247     CALL_DEBUG_ENTER;
248     auto cbIter = callbacks_.find(deviceId);
249     if (cbIter == callbacks_.end()) {
250         FI_HILOGW("This device is not exists");
251         return RET_OK;
252     }
253     std::list<ProfileEvent> profileEvents;
254     profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED);
255     std::list<ProfileEvent> failedEvents;
256     int32_t ret = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEvents,
257         cbIter->second, failedEvents);
258     callbacks_.erase(cbIter);
259     return ret;
260 }
261 
SaveSubscribeInfos(const std::string & deviceId,const std::shared_ptr<ProfileEventCallback> & callback,std::list<SubscribeInfo> & subscribeInfos)262 void FusionDeviceProfileAdapter::SaveSubscribeInfos(const std::string &deviceId,
263     const std::shared_ptr<ProfileEventCallback> &callback, std::list<SubscribeInfo> &subscribeInfos)
264 {
265     CALL_DEBUG_ENTER;
266     std::shared_ptr<ProfileEventCallback> profileEventCb;
267     auto cbIter = callbacks_.find(deviceId);
268     if ((cbIter == callbacks_.end()) || (cbIter->second == nullptr)) {
269         if (callback == nullptr) {
270             subscribeInfos.clear();
271             FI_HILOGE("Find callback for device %{public}s failed, and the given callback is nullptr",
272                 deviceId.c_str());
273             return;
274         }
275         callbacks_.insert_or_assign(deviceId, callback);
276         profileEventCb = callback;
277     } else {
278         profileEventCb = cbIter->second;
279     }
280 
281     for (auto iter = subscribeInfos.begin(); iter != subscribeInfos.end();) {
282         if (profileEventCb->SupportProfileEvent(iter->profileEvent)) {
283             iter = subscribeInfos.erase(iter);
284         } else {
285             ++iter;
286         }
287     }
288 }
289 
RemoveFailedSubscriptions(const std::string & deviceId,const std::list<ProfileEvent> & failedEvents)290 void FusionDeviceProfileAdapter::RemoveFailedSubscriptions(const std::string &deviceId,
291     const std::list<ProfileEvent> &failedEvents)
292 {
293     CALL_DEBUG_ENTER;
294     std::shared_ptr<IProfileEventCallback> profileEventCb;
295     auto cbIter = callbacks_.find(deviceId);
296     if (cbIter == callbacks_.end()) {
297         FI_HILOGW("This device is not exists");
298         return;
299     }
300     if (cbIter->second == nullptr) {
301         callbacks_.erase(cbIter);
302         FI_HILOGW("This device is not exists");
303         return;
304     }
305 
306     cbIter->second->RemoveProfileEvents(failedEvents);
307     if (!cbIter->second->HasProfileEvent()) {
308         callbacks_.erase(deviceId);
309     }
310 }
311 
UpdateCrossSwitchState(size_t switchState)312 int32_t UpdateCrossSwitchState(size_t switchState)
313 {
314     CALL_DEBUG_ENTER;
315     return DelayedRefSingleton<FusionDeviceProfileAdapter>::GetInstance().UpdateCrossSwitchState(
316         static_cast<bool>(switchState));
317 }
318 
SyncCrossSwitchState(size_t switchState,CIStringVector * deviceIds)319 int32_t SyncCrossSwitchState(size_t switchState, CIStringVector* deviceIds)
320 {
321     CALL_DEBUG_ENTER;
322     CHKPR(deviceIds, RET_ERR);
323     CHKPR(deviceIds->get, RET_ERR);
324     CHKPR(deviceIds->getSize, RET_ERR);
325     std::vector<std::string> deviceId;
326 
327     for (size_t i = 0; i < deviceIds->getSize(deviceIds); ++i) {
328         const char* device_id = deviceIds->get(deviceIds, i);
329         CHKPR(device_id, RET_ERR);
330         deviceId.emplace_back(std::string(device_id));
331     }
332     return DelayedRefSingleton<FusionDeviceProfileAdapter>::GetInstance().SyncCrossSwitchState(
333         static_cast<bool>(switchState), deviceId);
334 }
335 
GetCrossSwitchState(const char * deviceId)336 int32_t GetCrossSwitchState(const char* deviceId)
337 {
338     CALL_DEBUG_ENTER;
339     CHKPR(deviceId, RET_ERR);
340     bool switchState =
341         DelayedRefSingleton<FusionDeviceProfileAdapter>::GetInstance().GetCrossSwitchState(std::string(deviceId));
342     return (static_cast<int32_t>(switchState));
343 }
344 
RegisterCrossStateListener(const char * deviceId,CICrossStateListener * listener)345 int32_t RegisterCrossStateListener(const char* deviceId, CICrossStateListener* listener)
346 {
347     CALL_DEBUG_ENTER;
348     CHKPR(deviceId, RET_ERR);
349     CHKPR(listener, RET_ERR);
350     auto profileCallback = std::make_shared<ProfileEventCallback>(listener);
351     return DelayedRefSingleton<FusionDeviceProfileAdapter>::GetInstance().RegisterCrossStateListener(
352         std::string(deviceId), profileCallback);
353 }
354 
UnregisterCrossStateListener(const char * deviceId)355 int32_t UnregisterCrossStateListener(const char* deviceId)
356 {
357     CALL_DEBUG_ENTER;
358     CHKPR(deviceId, RET_ERR);
359     return DelayedRefSingleton<FusionDeviceProfileAdapter>::GetInstance().UnregisterCrossStateListener(
360         std::string(deviceId));
361 }
362