• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "device_profile_adapter.h"
17 
18 #include <algorithm>
19 #include <mutex>
20 
21 #include "distributed_device_profile_client.h"
22 #include "service_characteristic_profile.h"
23 #include "sync_options.h"
24 
25 #include "coordination_util.h"
26 #include "devicestatus_define.h"
27 
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 using namespace OHOS::DeviceProfile;
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceProfileAdapter" };
34 const std::string SERVICE_ID { "deviceStatus" };
35 } // namespace
36 
DeviceProfileAdapter()37 DeviceProfileAdapter::DeviceProfileAdapter() {}
38 
~DeviceProfileAdapter()39 DeviceProfileAdapter::~DeviceProfileAdapter()
40 {
41     std::lock_guard<std::mutex> guard(adapterLock_);
42     profileEventCallbacks_.clear();
43     callbacks_.clear();
44 }
45 
UpdateCrossingSwitchState(bool state,const std::vector<std::string> & deviceIds)46 int32_t DeviceProfileAdapter::UpdateCrossingSwitchState(bool state, const std::vector<std::string> &deviceIds)
47 {
48     CALL_INFO_TRACE;
49     const std::string SERVICE_TYPE = "deviceStatus";
50     ServiceCharacteristicProfile profile;
51     profile.SetServiceId(SERVICE_ID);
52     profile.SetServiceType(SERVICE_TYPE);
53     cJSON *data = cJSON_CreateObject();
54     cJSON_AddItemToObject(data, characteristicsName_.c_str(), cJSON_CreateNumber(state));
55     char *smsg = cJSON_Print(data);
56     cJSON_Delete(data);
57     profile.SetCharacteristicProfileJson(smsg);
58     cJSON_free(smsg);
59 
60     int32_t ret = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
61     if (ret != 0) {
62         FI_HILOGE("Put device profile failed, ret:%{public}d", ret);
63         return ret;
64     }
65     SyncOptions syncOptions;
66     std::for_each(deviceIds.begin(), deviceIds.end(),
67                   [&syncOptions](auto &deviceId) {
68                       syncOptions.AddDevice(deviceId);
69                       FI_HILOGD("Add device success");
70                   });
71     auto syncCallback = std::make_shared<DeviceProfileAdapter::ProfileEventCallbackImpl>();
72     ret =
73         DistributedDeviceProfileClient::GetInstance().SyncDeviceProfile(syncOptions, syncCallback);
74     if (ret != 0) {
75         FI_HILOGE("Sync device profile failed");
76     }
77     return ret;
78 }
79 
UpdateCrossingSwitchState(bool state)80 int32_t DeviceProfileAdapter::UpdateCrossingSwitchState(bool state)
81 {
82     CALL_INFO_TRACE;
83     const std::string SERVICE_TYPE = "deviceStatus";
84     ServiceCharacteristicProfile profile;
85     profile.SetServiceId(SERVICE_ID);
86     profile.SetServiceType(SERVICE_TYPE);
87     cJSON *data = cJSON_CreateObject();
88     cJSON_AddItemToObject(data, characteristicsName_.c_str(), cJSON_CreateNumber(state));
89     char *smsg = cJSON_Print(data);
90     cJSON_Delete(data);
91     profile.SetCharacteristicProfileJson(smsg);
92     cJSON_free(smsg);
93 
94     return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
95 }
96 
GetCrossingSwitchState(const std::string & deviceId)97 bool DeviceProfileAdapter::GetCrossingSwitchState(const std::string &deviceId)
98 {
99     CALL_INFO_TRACE;
100     ServiceCharacteristicProfile profile;
101     DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(deviceId, SERVICE_ID, profile);
102     std::string jsonData = profile.GetCharacteristicProfileJson();
103     JsonParser parser;
104     parser.json = cJSON_Parse(jsonData.c_str());
105     if (!cJSON_IsObject(parser.json)) {
106         FI_HILOGE("Parser json is not object");
107         return false;
108     }
109     cJSON* state = cJSON_GetObjectItemCaseSensitive(parser.json, characteristicsName_.c_str());
110     if (!cJSON_IsNumber(state)) {
111         FI_HILOGE("State is not number type");
112         return false;
113     }
114     return (static_cast<bool>(state->valueint));
115 }
116 
RegisterCrossingStateListener(const std::string & deviceId,DPCallback callback)117 int32_t DeviceProfileAdapter::RegisterCrossingStateListener(const std::string &deviceId, DPCallback callback)
118 {
119     CHKPR(callback, RET_ERR);
120     if (deviceId.empty()) {
121         FI_HILOGE("DeviceId is nullptr");
122         return RET_ERR;
123     }
124     std::lock_guard<std::mutex> guard(adapterLock_);
125     auto callbackIter = callbacks_.find(deviceId);
126     if (callbackIter != callbacks_.end()) {
127         callbackIter->second = callback;
128         FI_HILOGW("Callback is updated");
129         return RET_OK;
130     }
131     callbacks_[deviceId] = callback;
132     FI_HILOGI("Register crossing state listener success");
133     int32_t ret = RegisterProfileListener(deviceId);
134     if (ret != RET_OK) {
135         FI_HILOGE("Register profile listener failed");
136     }
137     return ret;
138 }
139 
UnregisterCrossingStateListener(const std::string & deviceId)140 int32_t DeviceProfileAdapter::UnregisterCrossingStateListener(const std::string &deviceId)
141 {
142     CALL_INFO_TRACE;
143     if (deviceId.empty()) {
144         FI_HILOGE("DeviceId is empty");
145         return RET_ERR;
146     }
147     std::lock_guard<std::mutex> guard(adapterLock_);
148     auto it = profileEventCallbacks_.find(deviceId);
149     if (it != profileEventCallbacks_.end()) {
150         std::list<ProfileEvent> profileEvents;
151         profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED);
152         std::list<ProfileEvent> failedEvents;
153         DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEvents,
154             it->second, failedEvents);
155         profileEventCallbacks_.erase(it);
156     }
157     auto callbackIter = callbacks_.find(deviceId);
158     if (callbackIter == callbacks_.end()) {
159         FI_HILOGW("This device has no callback");
160         return RET_OK;
161     }
162     callbacks_.erase(callbackIter);
163     return RET_OK;
164 }
165 
RegisterProfileListener(const std::string & deviceId)166 int32_t DeviceProfileAdapter::RegisterProfileListener(const std::string &deviceId)
167 {
168     CALL_INFO_TRACE;
169     std::list<std::string> serviceIdList;
170     serviceIdList.emplace_back(SERVICE_ID);
171     ExtraInfo extraInfo;
172     extraInfo["deviceId"] = deviceId;
173     extraInfo["serviceIds"] = serviceIdList;
174     SubscribeInfo changeEventInfo;
175     changeEventInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
176     changeEventInfo.extraInfo = std::move(extraInfo);
177     std::list<SubscribeInfo> subscribeInfos;
178     subscribeInfos.emplace_back(changeEventInfo);
179     SubscribeInfo syncEventInfo;
180     syncEventInfo.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED;
181     subscribeInfos.emplace_back(syncEventInfo);
182     std::list<ProfileEvent> failedEvents;
183     auto it = profileEventCallbacks_.find(deviceId);
184     if (it == profileEventCallbacks_.end() || it->second == nullptr) {
185         profileEventCallbacks_[deviceId] = std::make_shared<DeviceProfileAdapter::ProfileEventCallbackImpl>();
186     }
187     return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(
188         subscribeInfos, profileEventCallbacks_[deviceId], failedEvents);
189 }
190 
OnProfileChanged(const std::string & deviceId)191 void DeviceProfileAdapter::OnProfileChanged(const std::string &deviceId)
192 {
193     std::lock_guard<std::mutex> guard(adapterLock_);
194     auto it = callbacks_.find(deviceId);
195     if (it == callbacks_.end()) {
196         FI_HILOGW("The device has no callback");
197         return;
198     }
199     if (it->second != nullptr) {
200         auto state = GetCrossingSwitchState(deviceId);
201         it->second(deviceId, state);
202     } else {
203         callbacks_.erase(it);
204     }
205 }
206 
OnProfileChanged(const ProfileChangeNotification & changeNotification)207 void DeviceProfileAdapter::ProfileEventCallbackImpl::OnProfileChanged(
208     const ProfileChangeNotification &changeNotification)
209 {
210     CALL_INFO_TRACE;
211     std::string deviceId = changeNotification.GetDeviceId();
212     DP_ADAPTER->OnProfileChanged(deviceId);
213 }
214 
OnSyncCompleted(const DeviceProfile::SyncResult & syncResults)215 void DeviceProfileAdapter::ProfileEventCallbackImpl::OnSyncCompleted(const DeviceProfile::SyncResult &syncResults)
216 {
217     std::for_each(syncResults.begin(), syncResults.end(), [](const auto &syncResult) {
218         FI_HILOGD("Sync result:%{public}d", syncResult.second);
219     });
220 }
221 } // namespace DeviceStatus
222 } // namespace Msdp
223 } // namespace OHOS
224