• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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