• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 
21 #include "device_manager.h"
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 "service_characteristic_profile.h"
27 #include "trust_group_manager.h"
28 
29 #include "datetime_ex.h"
30 #include "profile_change_handler.h"
31 
32 namespace OHOS {
33 namespace DeviceProfile {
34 using namespace OHOS::DistributedKv;
35 using namespace std::chrono_literals;
36 
37 namespace {
38 const std::string TAG = "DeviceProfileStorage";
39 constexpr int32_t RETRY_TIMES_GET_KVSTORE = 10;
40 }
41 
DeviceProfileStorage(const std::string & appId,const std::string & storeId)42 DeviceProfileStorage::DeviceProfileStorage(const std::string& appId, const std::string& storeId)
43 {
44     appId_.appId = appId,
45     storeId_.storeId = storeId;
46 }
47 
SetOptions(const Options & options)48 void DeviceProfileStorage::SetOptions(const Options& options)
49 {
50     options_ = options;
51 }
52 
RegisterKvStoreInitCallback(const KvStoreInitCallback & callback)53 bool DeviceProfileStorage::RegisterKvStoreInitCallback(const KvStoreInitCallback& callback)
54 {
55     if (kvStoreInitCallback_ != nullptr) {
56         HILOGE("callback is not null");
57         return false;
58     }
59     kvStoreInitCallback_ = callback;
60     return true;
61 }
62 
Init()63 void DeviceProfileStorage::Init()
64 {
65     int64_t begin = GetTickCount();
66     std::unique_lock<std::shared_mutex> writeLock(storageLock_);
67     bool result = TryGetKvStore();
68     writeLock.unlock();
69     int64_t end = GetTickCount();
70     HILOGI("TryGetKvStore %{public}s, spend %{public}" PRId64 " ms",
71         result ? "succeeded" : "failed", end - begin);
72     // must call callback before set init status
73     if (kvStoreInitCallback_ != nullptr) {
74         kvStoreInitCallback_();
75     }
76     initStatus_ = StorageInitStatus::INIT_SUCCEED;
77 }
78 
SubscribeKvStore(const std::shared_ptr<KvStoreObserver> & observer)79 int32_t DeviceProfileStorage::SubscribeKvStore(const std::shared_ptr<KvStoreObserver>& observer)
80 {
81     HILOGD("called");
82     if (kvStorePtr_ == nullptr || observer == nullptr) {
83         return ERR_DP_INVALID_PARAMS;
84     }
85     Status status = kvStorePtr_->SubscribeKvStore(SubscribeType::DEFAULT, observer);
86     HILOGI("status %{public}d", status);
87     return static_cast<int32_t>(status);
88 }
89 
UnSubscribeKvStore(const std::shared_ptr<KvStoreObserver> & observer)90 int32_t DeviceProfileStorage::UnSubscribeKvStore(const std::shared_ptr<KvStoreObserver>& observer)
91 {
92     HILOGD("called");
93     if (kvStorePtr_ == nullptr || observer == nullptr) {
94         return ERR_DP_INVALID_PARAMS;
95     }
96     Status status = kvStorePtr_->UnSubscribeKvStore(SubscribeType::DEFAULT, observer);
97     HILOGI("status %{public}d", status);
98     return static_cast<int32_t>(status);
99 }
100 
RegisterSyncCallback(const std::shared_ptr<KvStoreSyncCallback> & sycnCb)101 int32_t DeviceProfileStorage::RegisterSyncCallback(const std::shared_ptr<KvStoreSyncCallback>& sycnCb)
102 {
103     HILOGD("called");
104     if (kvStorePtr_ == nullptr || sycnCb == nullptr) {
105         return ERR_DP_INVALID_PARAMS;
106     }
107     Status status = kvStorePtr_->RegisterSyncCallback(sycnCb);
108     HILOGI("status %{public}d", status);
109     return static_cast<int32_t>(status);
110 }
111 
UnRegisterSyncCallback()112 int32_t DeviceProfileStorage::UnRegisterSyncCallback()
113 {
114     HILOGD("called");
115     if (kvStorePtr_ == nullptr) {
116         return ERR_DP_INVALID_PARAMS;
117     }
118     Status status = kvStorePtr_->UnRegisterSyncCallback();
119     HILOGI("status %{public}d", status);
120     return static_cast<int32_t>(status);
121 }
122 
GetInitStatus()123 StorageInitStatus DeviceProfileStorage::GetInitStatus()
124 {
125     return initStatus_;
126 }
127 
TryGetKvStore()128 bool DeviceProfileStorage::TryGetKvStore()
129 {
130     int32_t retryTimes = 0;
131     while (retryTimes < RETRY_TIMES_GET_KVSTORE) {
132         if (GetKvStore() == Status::SUCCESS && kvStorePtr_ != nullptr) {
133             return true;
134         }
135         HILOGD("retry get kvstore...");
136         std::this_thread::sleep_for(500ms);
137         retryTimes++;
138     }
139     if (kvStorePtr_ == nullptr) {
140         initStatus_ = StorageInitStatus::INIT_FAILED;
141         return false;
142     }
143     return true;
144 }
145 
GetKvStore()146 Status DeviceProfileStorage::GetKvStore()
147 {
148     HILOGD("called");
149     Status status = dataManager_.GetSingleKvStore(options_, appId_, storeId_, kvStorePtr_);
150     if (status != Status::SUCCESS) {
151         HILOGI("get failed, error = %{public}d", status);
152     } else {
153         HILOGI("get succeeded");
154     }
155     return status;
156 }
157 
DeleteKvStore()158 void DeviceProfileStorage::DeleteKvStore()
159 {
160     Status status = dataManager_.DeleteKvStore(appId_, storeId_);
161     if (status != Status::SUCCESS) {
162         HILOGE("delete failed, error = %{public}d", status);
163     }
164 }
165 
GetDeviceProfile(const std::string & key,std::string & value)166 int32_t DeviceProfileStorage::GetDeviceProfile(const std::string& key, std::string& value)
167 {
168     std::shared_lock<std::shared_mutex> readLock(storageLock_);
169     if (kvStorePtr_ == nullptr) {
170         HILOGE("null kvstore");
171         return ERR_DP_INVALID_PARAMS;
172     }
173 
174     Key k(key);
175     Value v;
176     Status status = kvStorePtr_->Get(k, v);
177     if (status != Status::SUCCESS) {
178         HILOGE("get failed, %{public}d", status);
179         return static_cast<int32_t>(status);
180     }
181     value = v.ToString();
182     HILOGI("get succeeded");
183     return static_cast<int32_t>(status);
184 }
185 
PutDeviceProfile(const std::string & key,const std::string & value)186 int32_t DeviceProfileStorage::PutDeviceProfile(const std::string& key, const std::string& value)
187 {
188     std::unique_lock<std::shared_mutex> writeLock(storageLock_);
189     if (kvStorePtr_ == nullptr) {
190         HILOGE("null kvstore");
191         return ERR_DP_INVALID_PARAMS;
192     }
193 
194     Key k(key);
195     Value v(value);
196     Status status  = kvStorePtr_->Put(k, v);
197     if (status != Status::SUCCESS) {
198         HILOGE("put failed, error = %{public}d", status);
199     }
200     return static_cast<int32_t>(status);
201 }
202 
PutDeviceProfileBatch(const std::vector<std::string> & keys,const std::vector<std::string> & values)203 int32_t DeviceProfileStorage::PutDeviceProfileBatch(const std::vector<std::string>& keys,
204     const std::vector<std::string>& values)
205 {
206     std::unique_lock<std::shared_mutex> writeLock(storageLock_);
207     if (kvStorePtr_ == nullptr) {
208         HILOGE("null kvstore");
209         return ERR_DP_INVALID_PARAMS;
210     }
211 
212     const size_t keySize = keys.size();
213     const size_t valSize = values.size();
214     HILOGI("keySize = %{public}zu, valSize = %{public}zu", keySize, valSize);
215     if (keySize != valSize) {
216         HILOGE("diff key-value size");
217         return ERR_DP_INVALID_PARAMS;
218     }
219 
220     std::vector<Entry> entries;
221     entries.reserve(keySize);
222     for (uint32_t i = 0; i < keySize; i++) {
223         Entry entry;
224         entry.key = keys[i];
225         entry.value = values[i];
226         entries.emplace_back(entry);
227     }
228 
229     Status status = kvStorePtr_->PutBatch(entries);
230     if (status != Status::SUCCESS) {
231         HILOGE("put batch failed, error = %{public}d", status);
232     }
233     return static_cast<int32_t>(status);
234 }
235 
DeleteDeviceProfile(const std::string & key)236 int32_t DeviceProfileStorage::DeleteDeviceProfile(const std::string& key)
237 {
238     std::unique_lock<std::shared_mutex> writeLock(storageLock_);
239     if (kvStorePtr_ == nullptr) {
240         return ERR_DP_INVALID_PARAMS;
241     }
242     Key k(key);
243     Status status = kvStorePtr_->Delete(k);
244     if (status != Status::SUCCESS) {
245         HILOGE("delete failed, error = %{public}d", status);
246     }
247     return static_cast<int32_t>(status);
248 }
249 
SyncDeviceProfile(const std::vector<std::string> & deviceIdList,SyncMode syncMode)250 int32_t DeviceProfileStorage::SyncDeviceProfile(const std::vector<std::string>& deviceIdList,
251     SyncMode syncMode)
252 {
253     HILOGI("called");
254     if (!CheckTrustGroup(deviceIdList)) {
255         return ERR_DP_UNTRUSTED_GROUP;
256     }
257 
258     std::unique_lock<std::shared_mutex> writeLock(storageLock_);
259     if (kvStorePtr_ == nullptr) {
260         return ERR_DP_INVALID_PARAMS;
261     }
262 
263     Status status = kvStorePtr_->Sync(deviceIdList, static_cast<DistributedKv::SyncMode>(syncMode));
264     if (status != Status::SUCCESS) {
265         HILOGE("sync failed, error = %{public}d", status);
266     }
267     return static_cast<int32_t>(status);
268 }
269 
CheckTrustGroup(const std::vector<std::string> & deviceIdList)270 bool DeviceProfileStorage::CheckTrustGroup(const std::vector<std::string>& deviceIdList)
271 {
272     if (deviceIdList.empty()) {
273         HILOGE("device list is empty");
274         return false;
275     }
276     for (const auto& deviceId : deviceIdList) {
277         std::string udid;
278         if (!DeviceManager::GetInstance().TransformDeviceId(deviceId, udid, DeviceIdType::UDID)) {
279             HILOGE("%{public}s transform to udid failed", DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str());
280             return false;
281         }
282 
283         if (!TrustGroupManager::GetInstance().CheckTrustGroup(udid)) {
284             HILOGE("%{public}s not in trust group", DeviceProfileUtils::AnonymizeDeviceId(deviceId).c_str());
285             return false;
286         }
287     }
288     return true;
289 }
290 } // namespace DeviceProfile
291 } // namespace OHOS
292