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