1 /*
2 * Copyright (C) 2025 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 <thread>
19
20 #include "cJSON.h"
21 #include "device_profile_client.h"
22 #include "distributed_device_profile_errors.h"
23 #include "i_static_capability_collector.h"
24 #include "pasteboard_error.h"
25 #include "pasteboard_hilog.h"
26 #include "profile_change_listener_stub.h"
27 #include "system_ability_definition.h"
28
29 namespace OHOS {
30 namespace MiscServices {
31 using namespace OHOS::DistributedDeviceProfile;
32
33 constexpr const int32_t ERR_OK = 0;
34
35 constexpr const char *STATUS_ENABLE = "1";
36 constexpr const char *STATUS_DISABLE = "0";
37 constexpr const char *SERVICE_ID = "pasteboardService";
38 constexpr const char *STATIC_CHARACTER_ID = "static_capability";
39 constexpr const char *VERSION_ID = "PasteboardVersionId";
40 constexpr const char *CHARACTERISTIC_VALUE = "characteristicValue";
41 constexpr const char *SWITCH_ID = "SwitchStatus_Key_Distributed_Pasteboard";
42 constexpr const char *CHARACTER_ID = "SwitchStatus";
43
44 static IDeviceProfileAdapter::OnProfileUpdateCallback g_onProfileUpdateCallback = nullptr;
45
Bool2Str(bool value)46 static inline std::string Bool2Str(bool value)
47 {
48 return value ? STATUS_ENABLE : STATUS_DISABLE;
49 }
50
Str2Bool(const std::string & value)51 static inline bool Str2Bool(const std::string &value)
52 {
53 return value == STATUS_ENABLE;
54 }
55
56 class SubscribeDPChangeListener : public ProfileChangeListenerStub {
57 public:
58 SubscribeDPChangeListener() = default;
59 ~SubscribeDPChangeListener() = default;
60
OnTrustDeviceProfileAdd(const TrustDeviceProfile & profile)61 int32_t OnTrustDeviceProfileAdd(const TrustDeviceProfile &profile) override
62 {
63 (void)profile;
64 return ERR_OK;
65 }
66
OnTrustDeviceProfileDelete(const TrustDeviceProfile & profile)67 int32_t OnTrustDeviceProfileDelete(const TrustDeviceProfile &profile) override
68 {
69 (void)profile;
70 return ERR_OK;
71 }
72
OnTrustDeviceProfileUpdate(const TrustDeviceProfile & oldProfile,const TrustDeviceProfile & newProfile)73 int32_t OnTrustDeviceProfileUpdate(const TrustDeviceProfile &oldProfile,
74 const TrustDeviceProfile &newProfile) override
75 {
76 (void)oldProfile;
77 (void)newProfile;
78 return ERR_OK;
79 }
80
OnDeviceProfileAdd(const DeviceProfile & profile)81 int32_t OnDeviceProfileAdd(const DeviceProfile &profile) override
82 {
83 (void)profile;
84 return ERR_OK;
85 }
86
OnDeviceProfileDelete(const DeviceProfile & profile)87 int32_t OnDeviceProfileDelete(const DeviceProfile &profile) override
88 {
89 (void)profile;
90 return ERR_OK;
91 }
92
OnDeviceProfileUpdate(const DeviceProfile & oldProfile,const DeviceProfile & newProfile)93 int32_t OnDeviceProfileUpdate(const DeviceProfile &oldProfile, const DeviceProfile &newProfile) override
94 {
95 (void)oldProfile;
96 (void)newProfile;
97 return ERR_OK;
98 }
99
OnServiceProfileAdd(const ServiceProfile & profile)100 int32_t OnServiceProfileAdd(const ServiceProfile &profile) override
101 {
102 (void)profile;
103 return ERR_OK;
104 }
105
OnServiceProfileDelete(const ServiceProfile & profile)106 int32_t OnServiceProfileDelete(const ServiceProfile &profile) override
107 {
108 (void)profile;
109 return ERR_OK;
110 }
111
OnServiceProfileUpdate(const ServiceProfile & oldProfile,const ServiceProfile & newProfile)112 int32_t OnServiceProfileUpdate(const ServiceProfile &oldProfile, const ServiceProfile &newProfile) override
113 {
114 (void)oldProfile;
115 (void)newProfile;
116 return ERR_OK;
117 }
118
OnCharacteristicProfileAdd(const CharacteristicProfile & profile)119 int32_t OnCharacteristicProfileAdd(const CharacteristicProfile &profile) override
120 {
121 (void)profile;
122 return ERR_OK;
123 }
124
OnCharacteristicProfileDelete(const CharacteristicProfile & profile)125 int32_t OnCharacteristicProfileDelete(const CharacteristicProfile &profile) override
126 {
127 (void)profile;
128 return ERR_OK;
129 }
130
OnCharacteristicProfileUpdate(const CharacteristicProfile & oldProfile,const CharacteristicProfile & newProfile)131 int32_t OnCharacteristicProfileUpdate(const CharacteristicProfile &oldProfile,
132 const CharacteristicProfile &newProfile) override
133 {
134 std::string udid = newProfile.GetDeviceId();
135 std::string status = newProfile.GetCharacteristicValue();
136 if (g_onProfileUpdateCallback != nullptr) {
137 std::thread thread(g_onProfileUpdateCallback, udid, status == STATUS_ENABLE);
138 thread.detach();
139 }
140 return ERR_OK;
141 }
142 };
143
144 class DeviceProfileAdapter : public IDeviceProfileAdapter {
145 public:
146 int32_t RegisterUpdateCallback(const OnProfileUpdateCallback callback) override;
147 int32_t PutDeviceStatus(const std::string &udid, bool status) override;
148 int32_t GetDeviceStatus(const std::string &udid, bool &status) override;
149 bool GetDeviceVersion(const std::string &udid, uint32_t &versionId) override;
150 int32_t SubscribeProfileEvent(const std::string &udid) override;
151 int32_t UnSubscribeProfileEvent(const std::string &udid) override;
152 void SendSubscribeInfos() override;
153 void ClearDeviceProfileService() override;
154
155 private:
156 std::mutex mutex_;
157 std::unordered_map<std::string, SubscribeInfo> subscribeInfoCache_;
158 };
159
RegisterUpdateCallback(const OnProfileUpdateCallback callback)160 int32_t DeviceProfileAdapter::RegisterUpdateCallback(const OnProfileUpdateCallback callback)
161 {
162 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(callback != nullptr,
163 static_cast<int32_t>(PasteboardError::INVALID_PARAM_ERROR), PASTEBOARD_MODULE_COMMON, "callback is null");
164 g_onProfileUpdateCallback = callback;
165 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "success");
166 return static_cast<int32_t>(PasteboardError::E_OK);
167 }
168
PutDeviceStatus(const std::string & udid,bool status)169 int32_t DeviceProfileAdapter::PutDeviceStatus(const std::string &udid, bool status)
170 {
171 std::string enabledStatus = Bool2Str(status);
172 CharacteristicProfile profile;
173 profile.SetDeviceId(udid);
174 profile.SetServiceName(SWITCH_ID);
175 profile.SetCharacteristicKey(CHARACTER_ID);
176 profile.SetCharacteristicValue(enabledStatus);
177
178 int32_t ret = DeviceProfileClient::GetInstance().PutCharacteristicProfile(profile);
179 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == DistributedDeviceProfile::DP_SUCCESS ||
180 ret == DistributedDeviceProfile::DP_CACHE_EXIST, ret, PASTEBOARD_MODULE_COMMON,
181 "failed, udid=%{public}.5s, status=%{public}d, ret=%{public}d", udid.c_str(), status, ret);
182 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "success, udid=%{public}.5s, status=%{public}d", udid.c_str(), status);
183 return static_cast<int32_t>(PasteboardError::E_OK);
184 }
185
GetDeviceStatus(const std::string & udid,bool & status)186 int32_t DeviceProfileAdapter::GetDeviceStatus(const std::string &udid, bool &status)
187 {
188 CharacteristicProfile profile;
189 int32_t ret = DeviceProfileClient::GetInstance().GetCharacteristicProfile(udid,
190 SWITCH_ID, CHARACTER_ID, profile);
191 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == DistributedDeviceProfile::DP_SUCCESS, ret, PASTEBOARD_MODULE_COMMON,
192 "failed, udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
193
194 std::string enabledStatus = profile.GetCharacteristicValue();
195 status = Str2Bool(enabledStatus);
196 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "success, udid=%{public}.5s, status=%{public}d", udid.c_str(), status);
197 return static_cast<int32_t>(PasteboardError::E_OK);
198 }
199
GetDeviceVersion(const std::string & udid,uint32_t & versionId)200 bool DeviceProfileAdapter::GetDeviceVersion(const std::string &udid, uint32_t &versionId)
201 {
202 CharacteristicProfile profile;
203 int32_t ret = DeviceProfileClient::GetInstance().GetCharacteristicProfile(udid,
204 SERVICE_ID, STATIC_CHARACTER_ID, profile);
205 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == DistributedDeviceProfile::DP_SUCCESS, false, PASTEBOARD_MODULE_COMMON,
206 "get profile failed, udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
207
208 std::string jsonStr = profile.GetCharacteristicValue();
209 cJSON *jsonObj = cJSON_Parse(jsonStr.c_str());
210 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(jsonObj != nullptr, false, PASTEBOARD_MODULE_COMMON,
211 "parse profile failed, udid=%{public}.5s, profile=%{public}s", udid.c_str(), jsonStr.c_str());
212
213 cJSON *version = cJSON_GetObjectItemCaseSensitive(jsonObj, VERSION_ID);
214 if (version == nullptr || !cJSON_IsNumber(version) || (version->valuedouble < 0)) {
215 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "version not found, udid=%{public}.5s, profile=%{public}s",
216 udid.c_str(), jsonStr.c_str());
217 cJSON_Delete(jsonObj);
218 return false;
219 }
220
221 versionId = static_cast<uint32_t>(version->valuedouble);
222 cJSON_Delete(jsonObj);
223 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "udid=%{public}.5s, version=%{public}u", udid.c_str(), versionId);
224 return true;
225 }
226
SubscribeProfileEvent(const std::string & udid)227 int32_t DeviceProfileAdapter::SubscribeProfileEvent(const std::string &udid)
228 {
229 std::lock_guard lock(mutex_);
230 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(subscribeInfoCache_.find(udid) == subscribeInfoCache_.end(),
231 static_cast<int32_t>(PasteboardError::INVALID_PARAM_ERROR), PASTEBOARD_MODULE_COMMON,
232 "already exists, udid=%{public}.5s", udid.c_str());
233
234 SubscribeInfo subscribeInfo;
235 subscribeInfo.SetSaId(PASTEBOARD_SERVICE_ID);
236 subscribeInfo.SetSubscribeKey(udid, SWITCH_ID, CHARACTER_ID, CHARACTERISTIC_VALUE);
237 subscribeInfo.AddProfileChangeType(ProfileChangeType::CHAR_PROFILE_ADD);
238 subscribeInfo.AddProfileChangeType(ProfileChangeType::CHAR_PROFILE_UPDATE);
239 subscribeInfo.AddProfileChangeType(ProfileChangeType::CHAR_PROFILE_DELETE);
240 sptr<IProfileChangeListener> subscribeDPChangeListener = new (std::nothrow) SubscribeDPChangeListener;
241 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(subscribeDPChangeListener != nullptr,
242 static_cast<int32_t>(PasteboardError::MALLOC_FAILED), PASTEBOARD_MODULE_COMMON,
243 "malloc failed, udid=%{public}.5s", udid.c_str());
244
245 subscribeInfo.SetListener(subscribeDPChangeListener);
246 subscribeInfoCache_[udid] = subscribeInfo;
247
248 int32_t ret = DeviceProfileClient::GetInstance().SubscribeDeviceProfile(subscribeInfo);
249 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == DistributedDeviceProfile::DP_SUCCESS, ret, PASTEBOARD_MODULE_COMMON,
250 "failed, udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
251 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "success, udid=%{public}.5s", udid.c_str());
252 return static_cast<int32_t>(PasteboardError::E_OK);
253 }
254
UnSubscribeProfileEvent(const std::string & udid)255 int32_t DeviceProfileAdapter::UnSubscribeProfileEvent(const std::string &udid)
256 {
257 std::lock_guard lock(mutex_);
258 auto it = subscribeInfoCache_.find(udid);
259 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(it != subscribeInfoCache_.end(),
260 static_cast<int32_t>(PasteboardError::INVALID_PARAM_ERROR), PASTEBOARD_MODULE_COMMON,
261 "not find, udid=%{public}.5s", udid.c_str());
262
263 int32_t ret = DeviceProfileClient::GetInstance().UnSubscribeDeviceProfile(it->second);
264 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == DistributedDeviceProfile::DP_SUCCESS, ret, PASTEBOARD_MODULE_COMMON,
265 "failed, udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
266
267 subscribeInfoCache_.erase(it);
268 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "success, udid=%{public}.5s", udid.c_str());
269 return static_cast<int32_t>(PasteboardError::E_OK);
270 }
271
SendSubscribeInfos()272 void DeviceProfileAdapter::SendSubscribeInfos()
273 {
274 std::lock_guard lock(mutex_);
275 PASTEBOARD_CHECK_AND_RETURN_LOGI(!subscribeInfoCache_.empty(), PASTEBOARD_MODULE_COMMON,
276 "no subscribe info");
277
278 DeviceProfileClient::GetInstance().SendSubscribeInfos();
279 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "success, size=%{public}zu", subscribeInfoCache_.size());
280 }
281
ClearDeviceProfileService()282 void DeviceProfileAdapter::ClearDeviceProfileService()
283 {
284 DeviceProfileClient::GetInstance().ClearDeviceProfileService();
285 }
286
GetDeviceProfileAdapter()287 IDeviceProfileAdapter *GetDeviceProfileAdapter()
288 {
289 static DeviceProfileAdapter instance;
290 return &instance;
291 }
292
DeinitDeviceProfileAdapter()293 void DeinitDeviceProfileAdapter()
294 {
295 DeviceProfileClient::GetInstance().ClearDeviceProfileService();
296 g_onProfileUpdateCallback = nullptr;
297 }
298
299 class PasteboardStaticCapability : public IStaticCapabilityCollector {
300 public:
GetInstance()301 static PasteboardStaticCapability &GetInstance()
302 {
303 static PasteboardStaticCapability instance;
304 return instance;
305 }
306
IsSupportCapability()307 bool IsSupportCapability() override
308 {
309 return true;
310 }
311 };
312
313 extern "C" {
GetStaticCapabilityCollector()314 API_EXPORT IStaticCapabilityCollector *GetStaticCapabilityCollector()
315 {
316 return &PasteboardStaticCapability::GetInstance();
317 }
318 } // extern "C"
319
320 } // namespace MiscServices
321 } // namespace OHOS
322