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