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 "ddp_adapter_impl.h"
17
18 #include "devicestatus_define.h"
19 #include "json_parser.h"
20
21 namespace OHOS {
22 namespace Msdp {
23 namespace DeviceStatus {
24 namespace {
25 constexpr HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DDPAdapterImpl" };
26 const std::string SERVICE_ID { FI_PKG_NAME };
27 const std::string SERVICE_TYPE { FI_PKG_NAME };
28 } // namespace
29
30 #define DDP_CLIENT DeviceProfile::DistributedDeviceProfileClient::GetInstance()
31
OnSyncCompleted(const DeviceProfile::SyncResult & syncResults)32 void DDPAdapterImpl::ProfileEventCallback::OnSyncCompleted(const DeviceProfile::SyncResult &syncResults)
33 {
34 CALL_DEBUG_ENTER;
35 }
36
OnProfileChanged(const DeviceProfile::ProfileChangeNotification & changeNotification)37 void DDPAdapterImpl::ProfileEventCallback::OnProfileChanged(
38 const DeviceProfile::ProfileChangeNotification &changeNotification)
39 {
40 CALL_DEBUG_ENTER;
41 std::shared_ptr<DDPAdapterImpl> ddp = ddp_.lock();
42 if (ddp != nullptr) {
43 std::string networkId = changeNotification.GetDeviceId();
44 ddp->OnProfileChanged(networkId);
45 }
46 }
47
OnProfileChanged(const std::string & networkId)48 void DDPAdapterImpl::OnProfileChanged(const std::string &networkId)
49 {
50 std::lock_guard guard(mutex_);
51 for (const auto &item : observers_) {
52 std::shared_ptr<IDeviceProfileObserver> observer = item.Lock();
53 if (observer != nullptr) {
54 observer->OnProfileChanged(networkId);
55 }
56 }
57 }
58
AddObserver(std::shared_ptr<IDeviceProfileObserver> observer)59 void DDPAdapterImpl::AddObserver(std::shared_ptr<IDeviceProfileObserver> observer)
60 {
61 CALL_DEBUG_ENTER;
62 std::lock_guard guard(mutex_);
63 CHKPV(observer);
64 observers_.erase(Observer());
65 observers_.emplace(observer);
66 }
67
RemoveObserver(std::shared_ptr<IDeviceProfileObserver> observer)68 void DDPAdapterImpl::RemoveObserver(std::shared_ptr<IDeviceProfileObserver> observer)
69 {
70 CALL_DEBUG_ENTER;
71 std::lock_guard guard(mutex_);
72 if (auto iter = observers_.find(Observer(observer)); iter != observers_.end()) {
73 observers_.erase(iter);
74 }
75 observers_.erase(Observer());
76 }
77
AddWatch(const std::string & networkId)78 void DDPAdapterImpl::AddWatch(const std::string &networkId)
79 {
80 CALL_DEBUG_ENTER;
81 std::lock_guard guard(mutex_);
82 RegisterProfileListener(networkId);
83 siblings_.insert(networkId);
84 }
85
RemoveWatch(const std::string & networkId)86 void DDPAdapterImpl::RemoveWatch(const std::string &networkId)
87 {
88 CALL_DEBUG_ENTER;
89 std::lock_guard guard(mutex_);
90 siblings_.erase(networkId);
91 UnregisterProfileListener(networkId);
92 }
93
RegisterProfileListener(const std::string & networkId)94 int32_t DDPAdapterImpl::RegisterProfileListener(const std::string &networkId)
95 {
96 CALL_DEBUG_ENTER;
97 if (auto iter = profileEventCbs_.find(networkId); iter != profileEventCbs_.end()) {
98 return RET_OK;
99 }
100 std::list<std::string> serviceIds;
101 serviceIds.emplace_back(SERVICE_ID);
102
103 DeviceProfile::ExtraInfo extraInfo;
104 extraInfo["deviceId"] = networkId;
105 extraInfo["serviceIds"] = serviceIds;
106
107 DeviceProfile::SubscribeInfo changeEventInfo;
108 changeEventInfo.profileEvent = DeviceProfile::ProfileEvent::EVENT_PROFILE_CHANGED;
109 changeEventInfo.extraInfo = std::move(extraInfo);
110
111 std::list<DeviceProfile::SubscribeInfo> subscribeInfos;
112 subscribeInfos.emplace_back(changeEventInfo);
113
114 auto profileEventCb = std::make_shared<ProfileEventCallback>(shared_from_this());
115 std::list<DeviceProfile::ProfileEvent> failedEvents;
116 DDP_CLIENT.SubscribeProfileEvents(subscribeInfos, profileEventCb, failedEvents);
117
118 if (std::any_of(failedEvents.cbegin(), failedEvents.cend(),
119 [](DeviceProfile::ProfileEvent event) {
120 return (event == DeviceProfile::ProfileEvent::EVENT_PROFILE_CHANGED);
121 })) {
122 FI_HILOGE("SubscribeProfileEvents failed");
123 return RET_ERR;
124 }
125 profileEventCbs_.emplace(networkId, profileEventCb);
126 return RET_OK;
127 }
128
UnregisterProfileListener(const std::string & networkId)129 void DDPAdapterImpl::UnregisterProfileListener(const std::string &networkId)
130 {
131 CALL_DEBUG_ENTER;
132 auto iter = profileEventCbs_.find(networkId);
133 if (iter == profileEventCbs_.end()) {
134 return;
135 }
136 std::shared_ptr<ProfileEventCallback> profileEventCb = iter->second;
137 profileEventCbs_.erase(iter);
138
139 std::list<DeviceProfile::ProfileEvent> profileEvents;
140 profileEvents.emplace_back(DeviceProfile::ProfileEvent::EVENT_PROFILE_CHANGED);
141
142 std::list<DeviceProfile::ProfileEvent> failedEvents;
143 DDP_CLIENT.UnsubscribeProfileEvents(profileEvents, profileEventCb, failedEvents);
144 }
145
GetProperty(const std::string & networkId,const std::string & name,bool & value)146 int32_t DDPAdapterImpl::GetProperty(const std::string &networkId, const std::string &name, bool &value)
147 {
148 CALL_DEBUG_ENTER;
149 return GetProperty(networkId, name, [&value](cJSON *json) {
150 if (!cJSON_IsBool(json)) {
151 FI_HILOGE("Unexpected data type");
152 return RET_ERR;
153 }
154 value = (json->valueint != 0);
155 return RET_OK;
156 });
157 }
158
GetProperty(const std::string & networkId,const std::string & name,int32_t & value)159 int32_t DDPAdapterImpl::GetProperty(const std::string &networkId, const std::string &name, int32_t &value)
160 {
161 CALL_DEBUG_ENTER;
162 return GetProperty(networkId, name, [&value](cJSON *json) {
163 if (!cJSON_IsNumber(json)) {
164 FI_HILOGE("Unexpected data type");
165 return RET_ERR;
166 }
167 value = static_cast<int32_t>(json->valuedouble);
168 return RET_OK;
169 });
170 }
171
GetProperty(const std::string & networkId,const std::string & name,std::string & value)172 int32_t DDPAdapterImpl::GetProperty(const std::string &networkId, const std::string &name, std::string &value)
173 {
174 return GetProperty(networkId, name, [&value](cJSON *json) {
175 if (!cJSON_IsString(json) && !cJSON_IsRaw(json)) {
176 FI_HILOGE("Unexpected data type");
177 return RET_ERR;
178 }
179 CHKPR(json->valuestring, RET_ERR);
180 value = json->valuestring;
181 return RET_OK;
182 });
183 }
184
GetProperty(const std::string & networkId,const std::string & name,std::function<int32_t (cJSON * json)> parse)185 int32_t DDPAdapterImpl::GetProperty(const std::string &networkId, const std::string &name,
186 std::function<int32_t(cJSON *json)> parse)
187 {
188 CALL_DEBUG_ENTER;
189 DeviceProfile::ServiceCharacteristicProfile profile;
190 int32_t ret = DDP_CLIENT.GetDeviceProfile(networkId, SERVICE_ID, profile);
191 if (ret != RET_OK) {
192 FI_HILOGE("DP::GetDeviceProfile failed");
193 return RET_ERR;
194 }
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("Unexpected data format");
200 return RET_ERR;
201 }
202 cJSON* jsonValue = cJSON_GetObjectItem(parser.json, name.c_str());
203 if (jsonValue == nullptr) {
204 FI_HILOGE("Item \'%{public}s\' not found", name.c_str());
205 return RET_ERR;
206 }
207 return parse(jsonValue);
208 }
209
SetProperty(const std::string & name,bool value)210 int32_t DDPAdapterImpl::SetProperty(const std::string &name, bool value)
211 {
212 DPValue dpVal(std::in_place_type<bool>, value);
213 return SetProperty(name, dpVal);
214 }
215
SetProperty(const std::string & name,int32_t value)216 int32_t DDPAdapterImpl::SetProperty(const std::string &name, int32_t value)
217 {
218 DPValue dpVal(std::in_place_type<int32_t>, value);
219 return SetProperty(name, dpVal);
220 }
221
SetProperty(const std::string & name,const std::string & value)222 int32_t DDPAdapterImpl::SetProperty(const std::string &name, const std::string &value)
223 {
224 DPValue dpVal(std::in_place_type<std::string>, value);
225 return SetProperty(name, dpVal);
226 }
227
SetProperty(const std::string & name,const DPValue & value)228 int32_t DDPAdapterImpl::SetProperty(const std::string &name, const DPValue &value)
229 {
230 if (auto iter = properties_.find(name); iter != properties_.end()) {
231 if (iter->second == value) {
232 return RET_OK;
233 }
234 iter->second = value;
235 } else {
236 properties_.emplace(name, value);
237 }
238
239 PutProfile();
240 SyncProfile();
241 return RET_OK;
242 }
243
PutProfile()244 int32_t DDPAdapterImpl::PutProfile()
245 {
246 JsonParser parser;
247 parser.json = cJSON_CreateObject();
248 CHKPR(parser.json, RET_ERR);
249
250 for (const auto &[name, value] : properties_) {
251 JsonParser parser1;
252
253 std::visit(
254 [&parser1](const auto &arg) {
255 using T = std::decay_t<decltype(arg)>;
256
257 if constexpr(std::is_same_v<T, bool>) {
258 parser1.json = cJSON_CreateBool(arg);
259 } else if constexpr(std::is_same_v<T, int32_t>) {
260 parser1.json = cJSON_CreateNumber(arg);
261 } else if constexpr(std::is_same_v<T, std::string>) {
262 parser1.json = cJSON_CreateString(arg.c_str());
263 }
264 }, value);
265 CHKPR(parser1.json, RET_ERR);
266
267 if (!cJSON_AddItemToObject(parser.json, name.c_str(), parser1.json)) {
268 FI_HILOGE("Failed to add \'%{public}s\' to object", name.c_str());
269 return RET_ERR;
270 }
271 parser1.json = nullptr;
272 }
273
274 char *cProfile = cJSON_Print(parser.json);
275 CHKPR(cProfile, RET_ERR);
276 std::string sProfile(cProfile);
277 cJSON_free(cProfile);
278
279 DeviceProfile::ServiceCharacteristicProfile profile;
280 profile.SetServiceId(SERVICE_ID);
281 profile.SetServiceType(SERVICE_TYPE);
282 profile.SetCharacteristicProfileJson(sProfile);
283 int32_t ret = DDP_CLIENT.PutDeviceProfile(profile);
284 if (ret != RET_OK) {
285 FI_HILOGE("DP::PutDeviceProfile fail");
286 return RET_ERR;
287 }
288 return RET_OK;
289 }
290
SyncProfile()291 int32_t DDPAdapterImpl::SyncProfile()
292 {
293 DeviceProfile::SyncOptions syncOptions;
294 std::for_each(siblings_.cbegin(), siblings_.cend(),
295 [&syncOptions](auto &networkId) {
296 syncOptions.AddDevice(networkId);
297 });
298 auto syncCallback = std::make_shared<ProfileEventCallback>(shared_from_this());
299 int32_t ret = DDP_CLIENT.SyncDeviceProfile(syncOptions, syncCallback);
300 if (ret != RET_OK) {
301 FI_HILOGE("DP::SyncDeviceProfile failed");
302 return RET_ERR;
303 }
304 return RET_OK;
305 }
306 } // namespace DeviceStatus
307 } // namespace Msdp
308 } // namespace OHOS
309