1 /*
2 * Copyright (c) 2021-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 "distributed_device_profile_client.h"
17
18 #include <algorithm>
19 #include <bitset>
20 #include <chrono>
21 #include <functional>
22 #include <new>
23 #include <nlohmann/json.hpp>
24 #include <string>
25 #include <thread>
26 #include <type_traits>
27 #include <unistd.h>
28 #include <utility>
29
30 #include "callback/device_profile_load_callback.h"
31 #include "device_profile_errors.h"
32 #include "device_profile_log.h"
33 #include "event_handler.h"
34 #include "event_runner.h"
35 #include "idistributed_device_profile.h"
36 #include "if_system_ability_manager.h"
37 #include "ipc_skeleton.h"
38 #include "iremote_broker.h"
39 #include "iservice_registry.h"
40 #include "profile_event_notifier_stub.h"
41 #include "service_characteristic_profile.h"
42 #include "system_ability_definition.h"
43
44 namespace OHOS {
45 namespace DeviceProfile {
46 using namespace std::chrono_literals;
47
48 namespace {
49 const std::string TAG = "DistributedDeviceProfileClient";
50 const std::string JSON_NULL = "null";
51 constexpr int32_t DP_LOADSA_TIMEOUT_MS = 10000;
52 }
53
54 IMPLEMENT_SINGLE_INSTANCE(DistributedDeviceProfileClient);
55
LoadDeviceProfileService()56 bool DistributedDeviceProfileClient::LoadDeviceProfileService()
57 {
58 std::unique_lock<std::mutex> lock(serviceLock_);
59 sptr<DeviceProfileLoadCallback> loadCallback = new DeviceProfileLoadCallback();
60 if (loadCallback == nullptr) {
61 HILOGE("loadCallback is nullptr.");
62 return false;
63 }
64
65 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
66 if (samgrProxy == nullptr) {
67 HILOGE("get samgr failed");
68 return false;
69 }
70
71 int32_t ret = samgrProxy->LoadSystemAbility(DISTRIBUTED_DEVICE_PROFILE_SA_ID, loadCallback);
72 if (ret != ERR_OK) {
73 HILOGE("Failed to Load systemAbility");
74 return false;
75 }
76
77 auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(DP_LOADSA_TIMEOUT_MS),
78 [this]() { return dpProxy_ != nullptr; });
79 if (!waitStatus) {
80 HILOGE("dp load sa timeout");
81 return false;
82 }
83 return true;
84 }
85
LoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)86 void DistributedDeviceProfileClient::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
87 {
88 HILOGI("DistributedDeviceProfileClient FinishStartSA");
89 std::lock_guard<std::mutex> lock(serviceLock_);
90 if (dpDeathRecipient_ == nullptr) {
91 dpDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(
92 new DeviceProfileDeathRecipient);
93 }
94 if (remoteObject != nullptr) {
95 remoteObject->AddDeathRecipient(dpDeathRecipient_);
96 dpProxy_ = iface_cast<IDistributedDeviceProfile>(remoteObject);
97 proxyConVar_.notify_one();
98 }
99 }
100
LoadSystemAbilityFail()101 void DistributedDeviceProfileClient::LoadSystemAbilityFail()
102 {
103 std::lock_guard<std::mutex> lock(serviceLock_);
104 dpProxy_ = nullptr;
105 }
106
PutDeviceProfile(const ServiceCharacteristicProfile & profile)107 int32_t DistributedDeviceProfileClient::PutDeviceProfile(const ServiceCharacteristicProfile& profile)
108 {
109 if (CheckProfileInvalidity(profile)) {
110 return ERR_DP_INVALID_PARAMS;
111 }
112
113 auto dps = GetDeviceProfileService();
114 if (dps == nullptr) {
115 HILOGE("get dp service failed");
116 return ERR_DP_GET_SERVICE_FAILED;
117 }
118 return dps->PutDeviceProfile(profile);
119 }
120
GetDeviceProfile(const std::string & udid,const std::string & serviceId,ServiceCharacteristicProfile & profile)121 int32_t DistributedDeviceProfileClient::GetDeviceProfile(const std::string& udid, const std::string& serviceId,
122 ServiceCharacteristicProfile& profile)
123 {
124 auto dps = GetDeviceProfileService();
125 if (dps == nullptr) {
126 return ERR_DP_GET_SERVICE_FAILED;
127 }
128 return dps->GetDeviceProfile(udid, serviceId, profile);
129 }
130
DeleteDeviceProfile(const std::string & serviceId)131 int32_t DistributedDeviceProfileClient::DeleteDeviceProfile(const std::string& serviceId)
132 {
133 if (serviceId.empty()) {
134 return ERR_DP_INVALID_PARAMS;
135 }
136
137 auto dps = GetDeviceProfileService();
138 if (dps == nullptr) {
139 return ERR_DP_GET_SERVICE_FAILED;
140 }
141 return dps->DeleteDeviceProfile(serviceId);
142 }
143
SubscribeProfileEvent(const SubscribeInfo & subscribeInfo,const std::shared_ptr<IProfileEventCallback> & eventCb)144 int32_t DistributedDeviceProfileClient::SubscribeProfileEvent(const SubscribeInfo& subscribeInfo,
145 const std::shared_ptr<IProfileEventCallback>& eventCb)
146 {
147 std::list<SubscribeInfo> subscribeInfos;
148 subscribeInfos.emplace_back(subscribeInfo);
149 std::list<ProfileEvent> failedEvents;
150 return SubscribeProfileEvents(subscribeInfos, eventCb, failedEvents);
151 }
152
SubscribeProfileEvents(const std::list<SubscribeInfo> & subscribeInfos,const std::shared_ptr<IProfileEventCallback> & eventCb,std::list<ProfileEvent> & failedEvents)153 int32_t DistributedDeviceProfileClient::SubscribeProfileEvents(const std::list<SubscribeInfo>& subscribeInfos,
154 const std::shared_ptr<IProfileEventCallback>& eventCb,
155 std::list<ProfileEvent>& failedEvents)
156 {
157 if (subscribeInfos.empty() || eventCb == nullptr) {
158 return ERR_DP_INVALID_PARAMS;
159 }
160
161 ProfileEvents subProfileEvents;
162 for (auto& subscribeInfo : subscribeInfos) {
163 subProfileEvents.set(static_cast<uint32_t>(subscribeInfo.profileEvent));
164 }
165 // duplicated profile event is disallowed
166 if (subProfileEvents.count() != subscribeInfos.size()) {
167 return ERR_DP_INVALID_PARAMS;
168 }
169
170 std::unique_lock<std::mutex> autoLock(subscribeLock_);
171 sptr<IRemoteObject> notifier;
172 auto iter = subscribeRecords_.find(eventCb);
173 if (iter != subscribeRecords_.end()) {
174 notifier = iter->second.notifier;
175 } else {
176 notifier = sptr<ProfileEventNotifierStub>(
177 new ProfileEventNotifierStub(eventCb));
178 }
179 autoLock.unlock();
180
181 auto dps = GetDeviceProfileService();
182 if (dps == nullptr) {
183 return ERR_DP_GET_SERVICE_FAILED;
184 }
185
186 failedEvents.clear();
187 int32_t errCode = dps->SubscribeProfileEvents(subscribeInfos, notifier, failedEvents);
188 for (auto failedEvent : failedEvents) {
189 subProfileEvents.reset(static_cast<uint32_t>(failedEvent));
190 }
191
192 autoLock.lock();
193 iter = subscribeRecords_.find(eventCb);
194 if (iter != subscribeRecords_.end()) {
195 MergeSubscribeInfoLocked(iter->second.subscribeInfos, subscribeInfos);
196 iter->second.profileEvents |= subProfileEvents;
197 } else {
198 SubscribeRecord record {subscribeInfos, notifier, subProfileEvents};
199 subscribeRecords_.emplace(eventCb, std::move(record));
200 }
201 return errCode;
202 }
203
UnsubscribeProfileEvent(ProfileEvent profileEvent,const std::shared_ptr<IProfileEventCallback> & eventCb)204 int32_t DistributedDeviceProfileClient::UnsubscribeProfileEvent(ProfileEvent profileEvent,
205 const std::shared_ptr<IProfileEventCallback>& eventCb)
206 {
207 std::list<ProfileEvent> profileEvents;
208 profileEvents.emplace_back(profileEvent);
209 std::list<ProfileEvent> failedEvents;
210 return UnsubscribeProfileEvents(profileEvents, eventCb, failedEvents);
211 }
212
UnsubscribeProfileEvents(const std::list<ProfileEvent> & profileEvents,const std::shared_ptr<IProfileEventCallback> & eventCb,std::list<ProfileEvent> & failedEvents)213 int32_t DistributedDeviceProfileClient::UnsubscribeProfileEvents(const std::list<ProfileEvent>& profileEvents,
214 const std::shared_ptr<IProfileEventCallback>& eventCb,
215 std::list<ProfileEvent>& failedEvents)
216 {
217 if (profileEvents.empty() || eventCb == nullptr) {
218 return ERR_DP_INVALID_PARAMS;
219 }
220
221 std::unique_lock<std::mutex> autoLock(subscribeLock_);
222 ProfileEvents unsubProfileEvents;
223 for (auto profileEvent : profileEvents) {
224 unsubProfileEvents.set(static_cast<uint32_t>(profileEvent));
225 }
226 auto iter = subscribeRecords_.find(eventCb);
227 if (iter == subscribeRecords_.end()) {
228 return ERR_DP_NOT_SUBSCRIBED;
229 }
230 sptr<IRemoteObject> notifier = iter->second.notifier;
231 autoLock.unlock();
232
233 auto dps = GetDeviceProfileService();
234 if (dps == nullptr) {
235 return ERR_DP_GET_SERVICE_FAILED;
236 }
237
238 failedEvents.clear();
239 int32_t errCode = dps->UnsubscribeProfileEvents(profileEvents, notifier, failedEvents);
240 autoLock.lock();
241 iter = subscribeRecords_.find(eventCb);
242 if (iter != subscribeRecords_.end()) {
243 for (auto failedEvent : failedEvents) {
244 unsubProfileEvents.reset(static_cast<uint32_t>(failedEvent));
245 }
246 auto& subProfileEvents = iter->second.profileEvents;
247 subProfileEvents &= ~unsubProfileEvents;
248 if (subProfileEvents.none()) {
249 subscribeRecords_.erase(iter);
250 }
251 }
252 return errCode;
253 }
254
SyncDeviceProfile(const SyncOptions & syncOptions,const std::shared_ptr<IProfileEventCallback> & syncCb)255 int32_t DistributedDeviceProfileClient::SyncDeviceProfile(const SyncOptions& syncOptions,
256 const std::shared_ptr<IProfileEventCallback>& syncCb)
257 {
258 auto dps = GetDeviceProfileService();
259 if (dps == nullptr) {
260 return ERR_DP_GET_SERVICE_FAILED;
261 }
262
263 sptr<IRemoteObject> notifier =
264 sptr<ProfileEventNotifierStub>(new ProfileEventNotifierStub(syncCb));
265 return dps->SyncDeviceProfile(syncOptions, notifier);
266 }
267
GetDeviceProfileService()268 sptr<IDistributedDeviceProfile> DistributedDeviceProfileClient::GetDeviceProfileService()
269 {
270 {
271 std::lock_guard<std::mutex> lock(serviceLock_);
272 if (dpProxy_ != nullptr) {
273 return dpProxy_;
274 }
275 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
276 if (samgrProxy == nullptr) {
277 HILOGE("get samgr failed");
278 return nullptr;
279 }
280 auto object = samgrProxy->CheckSystemAbility(DISTRIBUTED_DEVICE_PROFILE_SA_ID);
281 if (object != nullptr) {
282 HILOGI("get service succeeded");
283 if (dpDeathRecipient_ == nullptr) {
284 dpDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(
285 new DeviceProfileDeathRecipient);
286 }
287 object->AddDeathRecipient(dpDeathRecipient_);
288 dpProxy_ = iface_cast<IDistributedDeviceProfile>(object);
289 return dpProxy_;
290 }
291 }
292
293 HILOGW("object is null");
294 if (LoadDeviceProfileService()) {
295 std::lock_guard<std::mutex> lock(serviceLock_);
296 if (dpProxy_ != nullptr) {
297 return dpProxy_;
298 } else {
299 HILOGE("load dp service failed");
300 return nullptr;
301 }
302 }
303 HILOGE("load dp service failed");
304 return nullptr;
305 }
306
CheckProfileInvalidity(const ServiceCharacteristicProfile & profile)307 bool DistributedDeviceProfileClient::CheckProfileInvalidity(const ServiceCharacteristicProfile& profile)
308 {
309 return profile.GetServiceId().empty() ||
310 profile.GetServiceType().empty() ||
311 profile.GetCharacteristicProfileJson().empty() ||
312 profile.GetCharacteristicProfileJson() == JSON_NULL;
313 }
314
MergeSubscribeInfoLocked(std::list<SubscribeInfo> & subscribeInfos,const std::list<SubscribeInfo> & newSubscribeInfos)315 void DistributedDeviceProfileClient::MergeSubscribeInfoLocked(std::list<SubscribeInfo>& subscribeInfos,
316 const std::list<SubscribeInfo>& newSubscribeInfos)
317 {
318 for (const auto& newSubscribeInfo : newSubscribeInfos) {
319 auto iter = std::find_if(subscribeInfos.begin(), subscribeInfos.end(),
320 [&newSubscribeInfo](const auto& subscribeInfo) {
321 return subscribeInfo.profileEvent == newSubscribeInfo.profileEvent;
322 });
323 if (iter == subscribeInfos.end()) {
324 subscribeInfos.emplace_back(newSubscribeInfo);
325 continue;
326 }
327 // override with the new subscribe info for same profile event
328 *iter = newSubscribeInfo;
329 }
330 }
331
OnServiceDied(const sptr<IRemoteObject> & remote)332 void DistributedDeviceProfileClient::OnServiceDied(const sptr<IRemoteObject>& remote)
333 {
334 HILOGI("called");
335 std::lock_guard<std::mutex> lock(serviceLock_);
336 dpProxy_ = nullptr;
337 }
338
OnRemoteDied(const wptr<IRemoteObject> & remote)339 void DistributedDeviceProfileClient::DeviceProfileDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
340 {
341 DistributedDeviceProfileClient::GetInstance().OnServiceDied(remote.promote());
342 }
343 } // namespace DeviceProfile
344 } // namespace OHOS
345