• 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 "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