1/*
2 * Copyright (c) 2022-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_database.h"
17
18#include "ans_log_wrapper.h"
19#include "device_manager.h"
20#include "distributed_preferences.h"
21
22namespace OHOS {
23namespace Notification {
24namespace {
25const std::string APP_ID = "notification_service";
26const std::string STORE_ID = "distributed_notification";
27constexpr char KV_STORE_PATH[] = "/data/service/el1/public/database/notification_service";
28}  // namespace
29
30DistributedDatabase::DistributedDatabase(
31    std::shared_ptr<DistributedDatabaseCallback> databaseCb, std::shared_ptr<DistributedDeviceCallback> deviceCb)
32    : DistributedFlowControl(), databaseCb_(databaseCb), deviceCb_(deviceCb)
33{
34    GetKvDataManager();
35}
36
37DistributedDatabase::~DistributedDatabase()
38{}
39
40void DistributedDatabase::GetKvDataManager()
41{
42    initCallback_ = std::make_shared<DeviceInitCallBack>();
43    int32_t ret = DistributedHardware::DeviceManager::GetInstance().InitDeviceManager(APP_ID + STORE_ID, initCallback_);
44    if (ret != ERR_OK) {
45        ANS_LOGE("init device manager failed, ret:%{public}d", ret);
46        return;
47    }
48    ret = DistributedHardware::DeviceManager::GetInstance().RegisterDevStateCallback(APP_ID + STORE_ID, "", deviceCb_);
49    if (ret != ERR_OK) {
50        ANS_LOGE("register devStateCallback failed, ret:%{public}d", ret);
51        return;
52    }
53
54    kvDataManager_ = std::make_unique<DistributedKv::DistributedKvDataManager>();
55    KvManagerFlowControlClear();
56}
57
58void DistributedDatabase::DeviceInitCallBack::OnRemoteDied()
59{
60    ANS_LOGW("DeviceInitCallBack OnRemoteDied");
61}
62
63bool DistributedDatabase::CheckKvDataManager()
64{
65    if (kvDataManager_ == nullptr) {
66        GetKvDataManager();
67    }
68    if (kvDataManager_ == nullptr) {
69        ANS_LOGE("kvDataManager_ is nullptr.");
70        return false;
71    }
72    return true;
73}
74
75void DistributedDatabase::GetKvStore()
76{
77    if (!CheckKvDataManager()) {
78        return;
79    }
80
81    bool enable = false;
82    DistributedPreferences::GetInstance()->GetDistributedEnable(enable);
83    if (!enable) {
84        ANS_LOGI("DistributedEnable is false, no need to create db.");
85        return;
86    }
87
88    DistributedKv::Options options {
89        .createIfMissing = true,
90        .encrypt = false,
91        .autoSync = false,
92        .securityLevel = DistributedKv::SecurityLevel::S1,
93        .area = DistributedKv::EL1,
94        .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
95        .baseDir = KV_STORE_PATH
96    };
97    DistributedKv::AppId appId = {.appId = APP_ID};
98    DistributedKv::StoreId storeId = {.storeId = STORE_ID};
99    DistributedKv::Status status = kvDataManager_->GetSingleKvStore(options, appId, storeId, kvStore_);
100    if (status != DistributedKv::Status::SUCCESS) {
101        ANS_LOGE("Failed to GetSingleKvStore ret = 0x%{public}x", status);
102        kvStore_.reset();
103        DistributedHardware::DeviceManager::GetInstance().UnRegisterDevStateCallback(APP_ID + STORE_ID);
104        kvDataManager_.reset();
105        return;
106    }
107
108    if (kvStore_ != nullptr) {
109        status = kvStore_->SubscribeKvStore(DistributedKv::SubscribeType::SUBSCRIBE_TYPE_REMOTE, databaseCb_);
110        if (status != DistributedKv::Status::SUCCESS) {
111            ANS_LOGE("kvStore SubscribeKvStore failed ret = 0x%{public}x", status);
112            kvStore_.reset();
113        }
114    }
115
116    KvStoreFlowControlClear();
117}
118
119bool DistributedDatabase::CheckKvStore()
120{
121    std::lock_guard<std::mutex> lock(mutex_);
122    if (kvStore_ == nullptr) {
123        GetKvStore();
124    }
125    if (kvStore_ == nullptr) {
126        ANS_LOGE("kvStore is nullptr.");
127        return false;
128    }
129    return true;
130}
131
132bool DistributedDatabase::OnDeviceConnected()
133{
134    return CheckKvStore();
135}
136
137bool DistributedDatabase::PutToDistributedDB(const std::string &key, const std::string &value)
138{
139    std::lock_guard<std::mutex> lock(mutex_);
140
141    if (kvStore_ == nullptr) {
142        ANS_LOGE("kvStore is null.");
143        return false;
144    }
145
146    if (!KvStoreFlowControl()) {
147        ANS_LOGE("KvStore flow control.");
148        return false;
149    }
150
151    DistributedKv::Key kvStoreKey(key);
152    DistributedKv::Value kvStoreValue(value);
153    DistributedKv::Status status = kvStore_->Put(kvStoreKey, kvStoreValue);
154    if (status != DistributedKv::Status::SUCCESS) {
155        ANS_LOGE("kvStore Put() failed ret = 0x%{public}x", status);
156        return false;
157    }
158
159    return true;
160}
161
162bool DistributedDatabase::GetFromDistributedDB(const std::string &key, std::string &value)
163{
164    std::lock_guard<std::mutex> lock(mutex_);
165
166    if (kvStore_ == nullptr) {
167        ANS_LOGE("kvStore is nullptr.");
168        return false;
169    }
170
171    if (!KvStoreFlowControl()) {
172        ANS_LOGE("KvStoreFlowControl is false.");
173        return false;
174    }
175
176    DistributedKv::Key kvStoreKey(key);
177    DistributedKv::Value kvStoreValue;
178    DistributedKv::Status status = kvStore_->Get(kvStoreKey, kvStoreValue);
179    if (status != DistributedKv::Status::SUCCESS) {
180        ANS_LOGE("kvStore Get() failed ret = 0x%{public}x", status);
181        return false;
182    }
183
184    value = kvStoreValue.ToString();
185
186    return true;
187}
188
189bool DistributedDatabase::GetEntriesFromDistributedDB(const std::string &prefixKey, std::vector<Entry> &entries)
190{
191    std::lock_guard<std::mutex> lock(mutex_);
192
193    if (kvStore_ == nullptr) {
194        ANS_LOGE("kvStore_ is nullptr.");
195        return false;
196    }
197
198    if (!KvStoreFlowControl()) {
199        ANS_LOGE("KvStoreFlowControl is fail.");
200        return false;
201    }
202
203    DistributedKv::Key kvStoreKey(prefixKey);
204    DistributedKv::Status status = kvStore_->GetEntries(kvStoreKey, entries);
205    if (status != DistributedKv::Status::SUCCESS) {
206        ANS_LOGE("kvStore GetEntries() failed ret = 0x%{public}x", status);
207        return false;
208    }
209
210    return true;
211}
212
213bool DistributedDatabase::DeleteToDistributedDB(const std::string &key)
214{
215    std::lock_guard<std::mutex> lock(mutex_);
216
217    if (kvStore_ == nullptr) {
218        ANS_LOGE("kvStore is nullptr.");
219        return false;
220    }
221
222    if (!KvStoreFlowControl()) {
223        ANS_LOGE("KvStoreFlowControl is defeat.");
224        return false;
225    }
226
227    DistributedKv::Key kvStoreKey(key);
228    DistributedKv::Status status = kvStore_->Delete(kvStoreKey);
229    if (status != DistributedKv::Status::SUCCESS) {
230        ANS_LOGE("kvStore Delete() failed ret = 0x%{public}x", status);
231        return false;
232    }
233
234    return true;
235}
236
237bool DistributedDatabase::ClearDataByDevice(const std::string &deviceId)
238{
239    std::lock_guard<std::mutex> lock(mutex_);
240
241    if (kvStore_ == nullptr) {
242        ANS_LOGE("kvStore is nullptr.");
243        return false;
244    }
245
246    if (!KvStoreFlowControl()) {
247        ANS_LOGE("KvStore flow control.");
248        return false;
249    }
250
251    DistributedKv::Status status = kvStore_->RemoveDeviceData(deviceId);
252    if (status != DistributedKv::Status::SUCCESS) {
253        ANS_LOGE("kvStore RemoveDeviceData() failed ret = 0x%{public}x", status);
254        return false;
255    }
256
257    return true;
258}
259
260bool DistributedDatabase::GetLocalDeviceId(std::string &deviceId)
261{
262    std::lock_guard<std::mutex> lock(mutex_);
263    if (!CheckKvDataManager()) {
264        return false;
265    }
266
267    if (KvManagerFlowControl()) {
268        DistributedHardware::DmDeviceInfo deviceInfo;
269        int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(APP_ID, deviceInfo);
270        if (ret != ERR_OK) {
271            ANS_LOGE("Get trust local device info failed ret = %{public}d", ret);
272            return false;
273        }
274        localDeviceId_ = deviceInfo.deviceId;
275    }
276
277    if (localDeviceId_.empty()) {
278        return false;
279    }
280
281    deviceId = localDeviceId_;
282
283    return true;
284}
285
286bool DistributedDatabase::GetLocalDeviceInfo(DeviceInfo &localInfo)
287{
288    std::lock_guard<std::mutex> lock(mutex_);
289    if (!CheckKvDataManager()) {
290        return false;
291    }
292
293    if (!KvManagerFlowControl()) {
294        ANS_LOGE("KvManager flow control.");
295        return false;
296    }
297
298    int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(APP_ID, localInfo);
299    if (ret != ERR_OK) {
300        ANS_LOGE("Get trust local device info failed ret = %{public}d", ret);
301        return false;
302    }
303
304    return true;
305}
306
307bool DistributedDatabase::GetDeviceInfoList(std::vector<DeviceInfo> &deviceList)
308{
309    std::lock_guard<std::mutex> lock(mutex_);
310    if (!CheckKvDataManager()) {
311        return false;
312    }
313
314    if (!KvManagerFlowControl()) {
315        ANS_LOGE("KvManager flow control.");
316        return false;
317    }
318
319    int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(APP_ID, "", deviceList);
320    if (ret != ERR_OK) {
321        ANS_LOGE("Get trust device list failed ret = %{public}d", ret);
322        return false;
323    }
324
325    return true;
326}
327
328bool DistributedDatabase::RecreateDistributedDB()
329{
330    std::lock_guard<std::mutex> lock(mutex_);
331    if (!CheckKvDataManager()) {
332        return false;
333    }
334
335    if (!KvManagerFlowControl()) {
336        ANS_LOGE("KvManager flow control.");
337        return false;
338    }
339    kvStore_.reset();
340    DistributedKv::AppId appId = {.appId = APP_ID};
341    DistributedKv::StoreId storeId = {.storeId = STORE_ID};
342    DistributedKv::Status status = kvDataManager_->DeleteKvStore(appId, storeId, KV_STORE_PATH);
343    if (status != DistributedKv::Status::SUCCESS) {
344        ANS_LOGE("kvDataManager DeleteKvStore() failed ret = 0x%{public}x", status);
345        return false;
346    }
347
348    return true;
349}
350}  // namespace Notification
351}  // namespace OHOS
352