1 /*
2 * Copyright (c) 2021-2024 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_storage.h"
17
18 #include <cinttypes>
19 #include <thread>
20 #include <unistd.h>
21
22 #include "device_profile_errors.h"
23 #include "device_profile_log.h"
24 #include "device_profile_storage_manager.h"
25 #include "device_profile_utils.h"
26 #include "dp_device_manager.h"
27 #include "service_characteristic_profile.h"
28 #include "trust_group_manager.h"
29
30 #include "datetime_ex.h"
31 #include "profile_change_handler.h"
32
33 namespace OHOS {
34 namespace DeviceProfile {
35 using namespace OHOS::DistributedKv;
36 using namespace std::chrono_literals;
37
38 namespace {
39 const std::string TAG = "DeviceProfileStorage";
40 const std::string PKG_NAME = "ohos.deviceprofile";
41 constexpr int32_t RETRY_TIMES_GET_KVSTORE = 1;
42 }
43
DeviceProfileStorage(const std::string & appId,const std::string & storeId)44 DeviceProfileStorage::DeviceProfileStorage(const std::string& appId, const std::string& storeId)
45 {
46 appId_.appId = appId,
47 storeId_.storeId = storeId;
48 }
49
SetOptions(const Options & options)50 void DeviceProfileStorage::SetOptions(const Options& options)
51 {
52 options_ = options;
53 }
54
RegisterKvStoreInitCallback(const KvStoreInitCallback & callback)55 bool DeviceProfileStorage::RegisterKvStoreInitCallback(const KvStoreInitCallback& callback)
56 {
57 if (kvStoreInitCallback_ != nullptr) {
58 HILOGE("callback is not null");
59 return false;
60 }
61 kvStoreInitCallback_ = callback;
62 return true;
63 }
64
Init()65 void DeviceProfileStorage::Init()
66 {
67 int64_t begin = GetTickCount();
68 std::unique_lock<std::shared_mutex> writeLock(storageLock_);
69 bool result = TryGetKvStore();
70 writeLock.unlock();
71 int64_t end = GetTickCount();
72 HILOGI("TryGetKvStore %{public}s, spend %{public}" PRId64 " ms",
73 result ? "succeeded" : "failed", end - begin);
74 // must call callback before set init status
75 if (result && kvStoreInitCallback_ != nullptr) {
76 kvStoreInitCallback_();
77 }
78 if (result) {
79 initStatus_ = StorageInitStatus::INIT_SUCCEED;
80 }
81 }
82
SubscribeKvStore(const std::shared_ptr<KvStoreObserver> & observer)83 int32_t DeviceProfileStorage::SubscribeKvStore(const std::shared_ptr<KvStoreObserver>& observer)
84 {
85 HILOGD("called");
86 if (kvStorePtr_ == nullptr || observer == nullptr) {
87 return ERR_DP_INVALID_PARAMS;
88 }
89 Status status = kvStorePtr_->SubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_REMOTE, observer);
90 HILOGI("status %{public}d", status);
91 return static_cast<int32_t>(status);
92 }
93
UnSubscribeKvStore(const std::shared_ptr<KvStoreObserver> & observer)94 int32_t DeviceProfileStorage::UnSubscribeKvStore(const std::shared_ptr<KvStoreObserver>& observer)
95 {
96 HILOGD("called");
97 if (kvStorePtr_ == nullptr || observer == nullptr) {
98 return ERR_DP_INVALID_PARAMS;
99 }
100 Status status = kvStorePtr_->UnSubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_REMOTE, observer);
101 HILOGI("status %{public}d", status);
102 return static_cast<int32_t>(status);
103 }
104
RegisterSyncCallback(const std::shared_ptr<KvStoreSyncCallback> & sycnCb)105 int32_t DeviceProfileStorage::RegisterSyncCallback(const std::shared_ptr<KvStoreSyncCallback>& sycnCb)
106 {
107 HILOGD("called");
108 if (kvStorePtr_ == nullptr || sycnCb == nullptr) {
109 return ERR_DP_INVALID_PARAMS;
110 }
111 Status status = kvStorePtr_->RegisterSyncCallback(sycnCb);
112 HILOGI("status %{public}d", status);
113 return static_cast<int32_t>(status);
114 }
115
UnRegisterSyncCallback()116 int32_t DeviceProfileStorage::UnRegisterSyncCallback()
117 {
118 HILOGD("called");
119 if (kvStorePtr_ == nullptr) {
120 return ERR_DP_INVALID_PARAMS;
121 }
122 Status status = kvStorePtr_->UnRegisterSyncCallback();
123 HILOGI("status %{public}d", status);
124 return static_cast<int32_t>(status);
125 }
126
GetInitStatus()127 StorageInitStatus DeviceProfileStorage::GetInitStatus()
128 {
129 HILOGI("GetInitStatus %{public}d", static_cast<int32_t>(initStatus_.load()));
130 return initStatus_;
131 }
132
TryGetKvStore()133 bool DeviceProfileStorage::TryGetKvStore()
134 {
135 int32_t retryTimes = 0;
136 while (retryTimes < RETRY_TIMES_GET_KVSTORE) {
137 if (GetKvStore() == Status::SUCCESS && kvStorePtr_ != nullptr) {
138 return true;
139 }
140 HILOGD("retry get kvstore...");
141 retryTimes++;
142 }
143 if (kvStorePtr_ == nullptr) {
144 initStatus_ = StorageInitStatus::INIT_FAILED;
145 return false;
146 }
147 return true;
148 }
149
GetKvStore()150 Status DeviceProfileStorage::GetKvStore()
151 {
152 HILOGD("called");
153 Status status = dataManager_.GetSingleKvStore(options_, appId_, storeId_, kvStorePtr_);
154 if (status != Status::SUCCESS) {
155 HILOGI("get failed, error = %{public}d", status);
156 } else {
157 HILOGI("get succeeded");
158 }
159 return status;
160 }
161
DeleteKvStore()162 void DeviceProfileStorage::DeleteKvStore()
163 {
164 Status status = dataManager_.DeleteKvStore(appId_, storeId_, options_.baseDir);
165 if (status != Status::SUCCESS) {
166 HILOGE("delete failed, error = %{public}d", status);
167 }
168 }
169
GetDeviceProfile(const std::string & key,std::string & value)170 int32_t DeviceProfileStorage::GetDeviceProfile(const std::string& key, std::string& value)
171 {
172 std::shared_lock<std::shared_mutex> readLock(storageLock_);
173 if (kvStorePtr_ == nullptr) {
174 HILOGE("null kvstore");
175 return ERR_DP_INVALID_PARAMS;
176 }
177
178 Key k(key);
179 Value v;
180 Status status = kvStorePtr_->Get(k, v);
181 if (status != Status::SUCCESS) {
182 HILOGE("get failed, %{public}d", status);
183 return static_cast<int32_t>(status);
184 }
185 value = v.ToString();
186 HILOGI("get succeeded");
187 return static_cast<int32_t>(status);
188 }
189
PutDeviceProfile(const std::string & key,const std::string & value)190 int32_t DeviceProfileStorage::PutDeviceProfile(const std::string& key, const std::string& value)
191 {
192 std::unique_lock<std::shared_mutex> writeLock(storageLock_);
193 if (kvStorePtr_ == nullptr) {
194 HILOGE("null kvstore");
195 return ERR_DP_INVALID_PARAMS;
196 }
197
198 Key kvKey(key);
199 Value oldV;
200 if (kvStorePtr_->Get(kvKey, oldV) == Status::SUCCESS && oldV.ToString() == value) {
201 HILOGD("The key-value pair already exists. key=%{public}s,value=%{public}s",
202 DeviceProfileUtils::AnonymizeDeviceId(key).c_str(), DeviceProfileUtils::AnonymizeDeviceId(value).c_str());
203 return ERR_OK;
204 }
205
206 Value kvValue(value);
207 Status status = kvStorePtr_->Put(kvKey, kvValue);
208 if (status != Status::SUCCESS) {
209 HILOGE("put failed, error = %{public}d", status);
210 }
211 return static_cast<int32_t>(status);
212 }
213
PutDeviceProfileBatch(const std::vector<std::string> & keys,const std::vector<std::string> & values)214 int32_t DeviceProfileStorage::PutDeviceProfileBatch(const std::vector<std::string>& keys,
215 const std::vector<std::string>& values)
216 {
217 std::unique_lock<std::shared_mutex> writeLock(storageLock_);
218 if (kvStorePtr_ == nullptr) {
219 HILOGE("null kvstore");
220 return ERR_DP_INVALID_PARAMS;
221 }
222
223 const size_t keySize = keys.size();
224 const size_t valSize = values.size();
225 HILOGI("keySize = %{public}zu, valSize = %{public}zu", keySize, valSize);
226 if (keySize != valSize) {
227 HILOGE("diff key-value size");
228 return ERR_DP_INVALID_PARAMS;
229 }
230
231 std::vector<Entry> entries;
232 Value oldV;
233 Key kvKey;
234 for (uint32_t i = 0; i < keySize; i++) {
235 kvKey = keys[i];
236 if (kvStorePtr_->Get(kvKey, oldV) == Status::SUCCESS && oldV.ToString() == values[i]) {
237 HILOGD("The key-value pair already exists. key=%{public}s,value=%{public}s",
238 DeviceProfileUtils::AnonymizeDeviceId(keys[i]).c_str(),
239 DeviceProfileUtils::AnonymizeDeviceId(values[i]).c_str());
240 continue;
241 }
242
243 Entry entry;
244 entry.key = kvKey;
245 entry.value = values[i];
246 entries.emplace_back(entry);
247 }
248 if (entries.empty()) {
249 HILOGD("All key-value pair already exists.");
250 return ERR_OK;
251 }
252
253 Status status = kvStorePtr_->PutBatch(entries);
254 if (status != Status::SUCCESS) {
255 HILOGE("put batch failed, error = %{public}d", status);
256 }
257 return static_cast<int32_t>(status);
258 }
259
DeleteDeviceProfile(const std::string & key)260 int32_t DeviceProfileStorage::DeleteDeviceProfile(const std::string& key)
261 {
262 std::unique_lock<std::shared_mutex> writeLock(storageLock_);
263 if (kvStorePtr_ == nullptr) {
264 return ERR_DP_INVALID_PARAMS;
265 }
266 Key k(key);
267 Status status = kvStorePtr_->Delete(k);
268 if (status != Status::SUCCESS) {
269 HILOGE("delete failed, error = %{public}d", status);
270 }
271 return static_cast<int32_t>(status);
272 }
273
SyncDeviceProfile(const std::vector<std::string> & deviceIdList,SyncMode syncMode)274 int32_t DeviceProfileStorage::SyncDeviceProfile(const std::vector<std::string>& deviceIdList,
275 SyncMode syncMode)
276 {
277 HILOGI("called");
278 std::vector<std::string> trustDeviceList = CheckTrustDeviceList(deviceIdList);
279 if (trustDeviceList.empty()) {
280 HILOGE("trust device list is empty");
281 return ERR_DP_UNTRUSTED_GROUP;
282 }
283
284 std::unique_lock<std::shared_mutex> writeLock(storageLock_);
285 if (kvStorePtr_ == nullptr) {
286 return ERR_DP_INVALID_PARAMS;
287 }
288
289 Status status = kvStorePtr_->Sync(trustDeviceList, static_cast<DistributedKv::SyncMode>(syncMode));
290 if (status != Status::SUCCESS) {
291 HILOGE("sync failed, error = %{public}d", status);
292 }
293 return static_cast<int32_t>(status);
294 }
295
RemoveDeviceData(const std::string networkId)296 int32_t DeviceProfileStorage::RemoveDeviceData(const std::string networkId)
297 {
298 HILOGI("called");
299
300 std::unique_lock<std::shared_mutex> writeLock(storageLock_);
301 if (kvStorePtr_ == nullptr) {
302 HILOGE("null kvstore");
303 return ERR_DP_INVALID_PARAMS;
304 }
305
306 Status status = kvStorePtr_->RemoveDeviceData(networkId);
307 if (status != Status::SUCCESS) {
308 HILOGE("remote device data failed, error = %{public}d", status);
309 }
310 return static_cast<int32_t>(status);
311 }
312
CheckTrustGroup(const std::vector<std::string> & deviceIdList)313 bool DeviceProfileStorage::CheckTrustGroup(const std::vector<std::string>& deviceIdList)
314 {
315 if (deviceIdList.empty()) {
316 HILOGE("device list is empty");
317 return false;
318 }
319 for (const auto& deviceId : deviceIdList) {
320 std::string udid;
321 if (!DpDeviceManager::GetInstance().TransformDeviceId(deviceId, udid, DeviceIdType::UDID)) {
322 HILOGE("%{public}s transform to udid failed", DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str());
323 return false;
324 }
325
326 if (!TrustGroupManager::GetInstance().CheckTrustGroup(udid)) {
327 HILOGE("%{public}s not in trust group", DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str());
328 return false;
329 }
330 }
331 return true;
332 }
333
CheckTrustDeviceList(const std::vector<std::string> & deviceIdList)334 std::vector<std::string> DeviceProfileStorage::CheckTrustDeviceList(const std::vector<std::string> &deviceIdList)
335 {
336 std::vector<std::string> trustDevices;
337 if (deviceIdList.empty()) {
338 HILOGE("device list is empty");
339 return trustDevices;
340 }
341 std::vector<std::string> onlineDevices = GetOnlineDevices();
342 for (const auto& deviceId : deviceIdList) {
343 auto iter = find(onlineDevices.begin(), onlineDevices.end(), deviceId);
344 if (iter != onlineDevices.end()) {
345 HILOGI("%{public}s add to trust devices", DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str());
346 trustDevices.push_back(deviceId);
347 }
348 }
349 return trustDevices;
350 }
351
GetOnlineDevices()352 std::vector<std::string> DeviceProfileStorage::GetOnlineDevices()
353 {
354 std::vector<std::string> targetDevices;
355 std::vector<DistributedHardware::DmDeviceInfo> allOnlineDeviceInfos;
356 int32_t result =
357 DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", allOnlineDeviceInfos);
358 if (result != Status::SUCCESS || allOnlineDeviceInfos.empty()) {
359 HILOGE("GetTrustedDeviceList Failed!");
360 return {};
361 }
362 for (const auto& dmDeviceInfo : allOnlineDeviceInfos) {
363 targetDevices.push_back(dmDeviceInfo.networkId);
364 }
365 HILOGI("online device size is %{public}zu", targetDevices.size());
366 return targetDevices;
367 }
368
GetDeviceProfile(const std::string & udid,const std::string & key,std::string & value)369 int32_t DeviceProfileStorage::GetDeviceProfile(const std::string& udid, const std::string& key, std::string& value)
370 {
371 HILOGI("call");
372 if (udid.empty() || key.empty()) {
373 HILOGE("udid or key invalid");
374 return ERR_DP_INVALID_PARAMS;
375 }
376 Key k(key);
377 Value v;
378 Status status;
379 {
380 std::shared_lock<std::shared_mutex> readLock(storageLock_);
381 if (kvStorePtr_ == nullptr) {
382 HILOGE("null kvstore");
383 return ERR_DP_INVALID_PARAMS;
384 }
385 status = kvStorePtr_->Get(k, v);
386 HILOGI("Get data status: %{public}d", status);
387 }
388 if (status == Status::NOT_FOUND) {
389 std::vector<std::string> device;
390 device.push_back(udid);
391 SyncMode syncMode{ SyncMode::PUSH_PULL };
392 int32_t res = SyncDeviceProfile(device, syncMode);
393 HILOGI("SyncDeviceProfile res: %{public}d!", res);
394 return static_cast<int32_t>(status);
395 }
396 if (status != Status::SUCCESS) {
397 HILOGE("get failed, %{public}d", status);
398 return static_cast<int32_t>(status);
399 }
400 value = v.ToString();
401 HILOGI("get succeeded");
402 return static_cast<int32_t>(status);
403 }
404 } // namespace DeviceProfile
405 } // namespace OHOS
406