• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "notification_rdb_data_mgr.h"
16 
17 #include "ans_log_wrapper.h"
18 #include "os_account_manager_helper.h"
19 #include "rdb_errno.h"
20 #include <algorithm>
21 #include <cstddef>
22 #include <sstream>
23 #include <string>
24 #include <vector>
25 #include "notification_analytics_util.h"
26 #include "notification_preferences.h"
27 #include "aes_gcm_helper.h"
28 
29 namespace OHOS {
30 namespace Notification {
31 namespace {
32 const std::string NOTIFICATION_KEY = "KEY";
33 const std::string NOTIFICATION_VALUE = "VALUE";
34 const int32_t NOTIFICATION_KEY_INDEX = 0;
35 const int32_t NOTIFICATION_VALUE_INDEX = 1;
36 const std::ptrdiff_t MAX_SIZE_PER_BATCH = 100;
37 const int32_t NOTIFICATION_RDB_MAX_MEMORY_SIZE = 1;
38 const std::string LIVE_VIEW_KEY = "secure_live_view";
39 } // namespace
RdbStoreDataCallBackNotificationStorage(const NotificationRdbConfig & notificationRdbConfig)40 RdbStoreDataCallBackNotificationStorage::RdbStoreDataCallBackNotificationStorage(
41     const NotificationRdbConfig &notificationRdbConfig): notificationRdbConfig_(notificationRdbConfig)
42 {
43     ANS_LOGD("create rdb store callback instance");
44 }
45 
~RdbStoreDataCallBackNotificationStorage()46 RdbStoreDataCallBackNotificationStorage::~RdbStoreDataCallBackNotificationStorage()
47 {
48     ANS_LOGD("destroy rdb store callback instance");
49 }
50 
OnCreate(NativeRdb::RdbStore & rdbStore)51 int32_t RdbStoreDataCallBackNotificationStorage::OnCreate(NativeRdb::RdbStore &rdbStore)
52 {
53     ANS_LOGD("OnCreate");
54     int ret = NativeRdb::E_OK;
55     if (hasTableInit_) {
56         return ret;
57     }
58     std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + notificationRdbConfig_.tableName
59         + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
60     ret = rdbStore.ExecuteSql(createTableSql);
61     if (ret == NativeRdb::E_OK) {
62         hasTableInit_ = true;
63         ANS_LOGD("createTable succeed");
64     }
65     return ret;
66 }
67 
OnUpgrade(NativeRdb::RdbStore & rdbStore,int32_t oldVersion,int32_t newVersion)68 int32_t RdbStoreDataCallBackNotificationStorage::OnUpgrade(
69     NativeRdb::RdbStore &rdbStore, int32_t oldVersion, int32_t newVersion)
70 {
71     ANS_LOGD("OnUpgrade currentVersion: %{public}d, targetVersion: %{public}d",
72         oldVersion, newVersion);
73 
74     if (oldVersion == 1) {
75         std::set<std::string> tables = GetTableNames(rdbStore);
76         if (tables.empty()) {
77             ANS_LOGE("Query tableName failed");
78             return NativeRdb::E_OK;
79         }
80 
81         for (const std::string &tableName : tables) {
82             if (!ProcessTable(rdbStore, tableName)) {
83                 return NativeRdb::E_OK;
84             }
85         }
86     }
87 
88     return NativeRdb::E_OK;
89 }
90 
GetTableNames(NativeRdb::RdbStore & rdbStore)91 std::set<std::string> RdbStoreDataCallBackNotificationStorage::GetTableNames(NativeRdb::RdbStore &rdbStore)
92 {
93     std::set<std::string> tables;
94     std::string queryTableSql = "SELECT name FROM sqlite_master WHERE type='table'";
95     auto absSharedResultSet = rdbStore.QuerySql(queryTableSql);
96     if (absSharedResultSet == nullptr) {
97         return tables;
98     }
99     int32_t ret = absSharedResultSet->GoToFirstRow();
100     if (ret != NativeRdb::E_OK) {
101         return tables;
102     }
103 
104     do {
105         std::string tableName;
106         ret = absSharedResultSet->GetString(0, tableName);
107         if (ret == NativeRdb::E_OK) {
108             tables.insert(tableName);
109         }
110     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
111 
112     return tables;
113 }
114 
ProcessTable(NativeRdb::RdbStore & rdbStore,const std::string & tableName)115 bool RdbStoreDataCallBackNotificationStorage::ProcessTable(
116     NativeRdb::RdbStore &rdbStore, const std::string &tableName)
117 {
118     auto absSharedResultSet = QueryTable(rdbStore, tableName);
119     if (!absSharedResultSet) {
120         return false;
121     }
122 
123     bool result = ProcessResultSet(absSharedResultSet, rdbStore, tableName);
124     absSharedResultSet->Close();
125     return result;
126 }
127 
QueryTable(NativeRdb::RdbStore & rdbStore,const std::string & tableName)128 std::shared_ptr<NativeRdb::AbsSharedResultSet> RdbStoreDataCallBackNotificationStorage::QueryTable(
129     NativeRdb::RdbStore &rdbStore, const std::string &tableName)
130 {
131     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
132     absRdbPredicates.BeginsWith(NOTIFICATION_KEY, LIVE_VIEW_KEY);
133     auto absSharedResultSet = rdbStore.Query(absRdbPredicates, std::vector<std::string>());
134     if (!absSharedResultSet) {
135         ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
136     }
137     return absSharedResultSet;
138 }
139 
ProcessResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,NativeRdb::RdbStore & rdbStore,const std::string & tableName)140 bool RdbStoreDataCallBackNotificationStorage::ProcessResultSet(
141     std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,
142     NativeRdb::RdbStore &rdbStore, const std::string &tableName)
143 {
144     absSharedResultSet->GoToFirstRow();
145     do {
146         if (!ProcessRow(absSharedResultSet, rdbStore, tableName)) {
147             return false;
148         }
149     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
150 
151     return true;
152 }
153 
ProcessRow(std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,NativeRdb::RdbStore & rdbStore,const std::string & tableName)154 bool RdbStoreDataCallBackNotificationStorage::ProcessRow(
155     std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,
156     NativeRdb::RdbStore &rdbStore, const std::string &tableName)
157 {
158     std::string resultKey;
159     if (!GetStringFromResultSet(absSharedResultSet, NOTIFICATION_KEY_INDEX, resultKey)) {
160         return false;
161     }
162 
163     std::string resultValue;
164     if (!GetStringFromResultSet(absSharedResultSet, NOTIFICATION_VALUE_INDEX, resultValue)) {
165         return false;
166     }
167 
168     std::string input;
169     AesGcmHelper::Decrypt(input, resultValue);
170     auto jsonObject = nlohmann::json::parse(input);
171 
172     auto *request = NotificationJsonConverter::ConvertFromJson<NotificationRequest>(jsonObject);
173     if (!request) {
174         ANS_LOGE("Parse json string to request failed.");
175         return true;
176     }
177 
178     auto *bundleOption = NotificationJsonConverter::ConvertFromJson<NotificationBundleOption>(jsonObject);
179     if (!bundleOption) {
180         ANS_LOGE("Parse json string to bundleOption failed.");
181         return true;
182     }
183 
184     ANS_LOGW("before change request: %{public}s.", request->Dump().c_str());
185     if (!UpdateRequest(request)) {
186         return true;
187     }
188 
189     if (!WriteBackToDatabase(request, bundleOption, rdbStore, tableName)) {
190         return false;
191     }
192 
193     return true;
194 }
195 
GetStringFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,int columnIndex,std::string & result)196 bool RdbStoreDataCallBackNotificationStorage::GetStringFromResultSet(
197     std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet, int columnIndex, std::string &result)
198 {
199     int32_t ret = absSharedResultSet->GetString(columnIndex, result);
200     if (ret != NativeRdb::E_OK) {
201         return false;
202     }
203     return true;
204 }
205 
WriteBackToDatabase(NotificationRequest * request,NotificationBundleOption * bundleOption,NativeRdb::RdbStore & rdbStore,const std::string & tableName)206 bool RdbStoreDataCallBackNotificationStorage::WriteBackToDatabase(
207     NotificationRequest *request, NotificationBundleOption *bundleOption,
208     NativeRdb::RdbStore &rdbStore, const std::string &tableName)
209 {
210     nlohmann::json jsonOutObject;
211     if (!NotificationJsonConverter::ConvertToJson(request, jsonOutObject) ||
212         !NotificationJsonConverter::ConvertToJson(bundleOption, jsonOutObject)) {
213         ANS_LOGE("Convert to json object failed");
214         return false;
215     }
216 
217     std::string encryptValue;
218     AesGcmHelper::Encrypt(jsonOutObject.dump(), encryptValue);
219     int64_t rowId = -1;
220     NativeRdb::ValuesBucket valuesBucket;
221     valuesBucket.PutString(NOTIFICATION_KEY, request->GetSecureKey());
222     valuesBucket.PutString(NOTIFICATION_VALUE, encryptValue);
223 
224     int32_t ret = rdbStore.InsertWithConflictResolution(rowId, tableName, valuesBucket,
225         NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
226     if (ret != NativeRdb::E_OK) {
227         ANS_LOGE("Insert failed with ret: %{public}d", ret);
228         return false;
229     }
230     ANS_LOGI("Insert success ret is %{public}d", ret);
231     return true;
232 }
233 
UpdateRequest(NotificationRequest * request)234 bool RdbStoreDataCallBackNotificationStorage::UpdateRequest(NotificationRequest *request)
235 {
236     auto actionButtons = request->GetActionButtons();
237     if (actionButtons.empty()) {
238         ANS_LOGE("ActionButtons is empty");
239         return false;
240     }
241 
242     auto firstButton = actionButtons.front();
243     auto firstButtonWantAgent = firstButton->GetWantAgent();
244     auto liveViewContent = std::static_pointer_cast<NotificationLiveViewContent>(
245         request->GetContent()->GetNotificationContent());
246     if (firstButtonWantAgent) {
247         liveViewContent->SetExtensionWantAgent(firstButtonWantAgent);
248     }
249     auto requestContent = std::make_shared<NotificationContent>(liveViewContent);
250     request->SetContent(requestContent);
251 
252     actionButtons.erase(actionButtons.begin());
253     request->ClearActionButtons();
254     for (auto actionButton : actionButtons) {
255         request->AddActionButton(actionButton);
256     }
257 
258     ANS_LOGW("End request: %{public}s.", request->Dump().c_str());
259     return true;
260 }
261 
OnDowngrade(NativeRdb::RdbStore & rdbStore,int currentVersion,int targetVersion)262 int32_t RdbStoreDataCallBackNotificationStorage::OnDowngrade(
263     NativeRdb::RdbStore &rdbStore, int currentVersion, int targetVersion)
264 {
265     ANS_LOGD("OnDowngrade  currentVersion: %{public}d, targetVersion: %{public}d",
266         currentVersion, targetVersion);
267     return NativeRdb::E_OK;
268 }
269 
OnOpen(NativeRdb::RdbStore & rdbStore)270 int32_t RdbStoreDataCallBackNotificationStorage::OnOpen(NativeRdb::RdbStore &rdbStore)
271 {
272     ANS_LOGD("OnOpen");
273     return NativeRdb::E_OK;
274 }
275 
onCorruption(std::string databaseFile)276 int32_t RdbStoreDataCallBackNotificationStorage::onCorruption(std::string databaseFile)
277 {
278     return NativeRdb::E_OK;
279 }
280 
NotificationDataMgr(const NotificationRdbConfig & notificationRdbConfig)281 NotificationDataMgr::NotificationDataMgr(const NotificationRdbConfig &notificationRdbConfig)
282     : notificationRdbConfig_(notificationRdbConfig)
283 {
284     ANS_LOGD("create notification rdb data manager");
285 }
286 
Init()287 int32_t NotificationDataMgr::Init()
288 {
289     ANS_LOGD("Create rdbStore");
290     {
291         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
292         if (rdbStore_ != nullptr) {
293             ANS_LOGD("notification rdb has existed");
294             return NativeRdb::E_OK;
295         }
296     }
297     NativeRdb::RdbStoreConfig rdbStoreConfig(
298             notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName,
299             NativeRdb::StorageMode::MODE_DISK,
300             false,
301             std::vector<uint8_t>(),
302             notificationRdbConfig_.journalMode,
303             notificationRdbConfig_.syncMode);
304     rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
305     rdbStoreConfig.SetHaMode(NativeRdb::HAMode::MAIN_REPLICA);
306     rdbStoreConfig.SetClearMemorySize(NOTIFICATION_RDB_MAX_MEMORY_SIZE);
307     RdbStoreDataCallBackNotificationStorage rdbDataCallBack_(notificationRdbConfig_);
308     std::lock_guard<ffrt::mutex> lock(createdTableMutex_);
309     {
310         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
311         int32_t ret = NativeRdb::E_OK;
312         rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, notificationRdbConfig_.version,
313             rdbDataCallBack_, ret);
314         if (rdbStore_ == nullptr) {
315             ANS_LOGE("notification rdb init fail");
316             return NativeRdb::E_ERROR;
317         }
318         return InitCreatedTables();
319     }
320 }
321 
InitCreatedTables()322 int32_t NotificationDataMgr::InitCreatedTables()
323 {
324     std::string queryTableSql = "SELECT name FROM sqlite_master WHERE type='table'";
325     auto absSharedResultSet = rdbStore_->QuerySql(queryTableSql);
326     int32_t ret = absSharedResultSet->GoToFirstRow();
327     if (ret != NativeRdb::E_OK) {
328         ANS_LOGE("Query tableName failed. It's empty!");
329         return NativeRdb::E_EMPTY_VALUES_BUCKET;
330     }
331 
332     do {
333         std::string tableName;
334         ret = absSharedResultSet->GetString(0, tableName);
335         if (ret != NativeRdb::E_OK) {
336             ANS_LOGE("GetString string failed from sqlite_master table.");
337             return NativeRdb::E_ERROR;
338         }
339         createdTables_.insert(tableName);
340     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
341     absSharedResultSet->Close();
342     ANS_LOGI("create tables successfully");
343     return NativeRdb::E_OK;
344 }
345 
Destroy()346 int32_t NotificationDataMgr::Destroy()
347 {
348     ANS_LOGD("Destory rdbStore");
349     std::lock_guard<ffrt::mutex> lock(createdTableMutex_);
350     createdTables_.clear();
351     {
352         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
353         if (rdbStore_ == nullptr) {
354             ANS_LOGE("notification rdb is null");
355             return NativeRdb::E_ERROR;
356         }
357 
358         rdbStore_ = nullptr;
359     }
360     int32_t ret = NativeRdb::RdbHelper::DeleteRdbStore(notificationRdbConfig_.dbPath + notificationRdbConfig_.dbName);
361     if (ret != NativeRdb::E_OK) {
362         ANS_LOGE("failed to destroy db store");
363         return NativeRdb::E_ERROR;
364     }
365     ANS_LOGI("destroy db store successfully");
366     return NativeRdb::E_OK;
367 }
368 
InsertData(const std::string & key,const std::string & value,const int32_t & userId)369 int32_t NotificationDataMgr::InsertData(const std::string &key, const std::string &value, const int32_t &userId)
370 {
371     ANS_LOGD("InsertData start");
372     {
373         HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_11, EventBranchId::BRANCH_0);
374         std::string tableName;
375         int32_t ret = GetUserTableName(userId, tableName);
376         if (ret != NativeRdb::E_OK) {
377             ANS_LOGE("Get user table name failed.");
378             return NativeRdb::E_ERROR;
379         }
380         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
381         if (rdbStore_ == nullptr) {
382             ANS_LOGE("notification rdb is null");
383             return NativeRdb::E_ERROR;
384         }
385         int64_t rowId = -1;
386         NativeRdb::ValuesBucket valuesBucket;
387         valuesBucket.PutString(NOTIFICATION_KEY, key);
388         valuesBucket.PutString(NOTIFICATION_VALUE, value);
389         ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
390             NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
391         if (ret == NativeRdb::E_SQLITE_CORRUPT) {
392             RestoreForMasterSlaver();
393         }
394         if (ret != NativeRdb::E_OK) {
395             ANS_LOGE("Insert operation failed, result: %{public}d, key=%{public}s.", ret, key.c_str());
396             message.ErrorCode(ret).Message("Insert operation failed.");
397             NotificationAnalyticsUtil::ReportModifyEvent(message);
398             return NativeRdb::E_ERROR;
399         }
400     }
401     SendUserDataSizeHisysevent();
402     return NativeRdb::E_OK;
403 }
404 
InsertData(const std::string & key,const std::vector<uint8_t> & value,const int32_t & userId)405 int32_t NotificationDataMgr::InsertData(const std::string &key, const std::vector<uint8_t> &value,
406     const int32_t &userId)
407 {
408     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_8);
409     std::string tableName;
410     int32_t ret = GetUserTableName(userId, tableName);
411     if (ret != NativeRdb::E_OK) {
412         ANS_LOGE("Get user table name failed.");
413         return NativeRdb::E_ERROR;
414     }
415     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
416     if (rdbStore_ == nullptr) {
417         ANS_LOGE("notification rdb is null");
418         return NativeRdb::E_ERROR;
419     }
420     int64_t rowId = -1;
421     NativeRdb::ValuesBucket valuesBucket;
422     valuesBucket.PutString(NOTIFICATION_KEY, key);
423     valuesBucket.PutBlob(NOTIFICATION_VALUE, value);
424     ret = rdbStore_->InsertWithConflictResolution(rowId, tableName, valuesBucket,
425         NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
426     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
427             RestoreForMasterSlaver();
428         }
429     if (ret != NativeRdb::E_OK) {
430         ANS_LOGE("Insert operation failed, result: %{public}d, key=%{public}s.", ret, key.c_str());
431         message.ErrorCode(ret).Message("Insert operation failed.");
432         NotificationAnalyticsUtil::ReportModifyEvent(message);
433         return NativeRdb::E_ERROR;
434     }
435     SendUserDataSizeHisysevent();
436     return NativeRdb::E_OK;
437 }
438 
InsertBatchData(const std::unordered_map<std::string,std::string> & values,const int32_t & userId)439 int32_t NotificationDataMgr::InsertBatchData(const std::unordered_map<std::string, std::string> &values,
440     const int32_t &userId)
441 {
442     ANS_LOGD("InsertBatchData start");
443     {
444         std::string tableName;
445         HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_7);
446         int32_t ret = GetUserTableName(userId, tableName);
447         if (ret != NativeRdb::E_OK) {
448             ANS_LOGE("Get user table name failed.");
449             return NativeRdb::E_ERROR;
450         }
451         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
452         if (rdbStore_ == nullptr) {
453             ANS_LOGE("notification rdb is null");
454             return NativeRdb::E_ERROR;
455         }
456         int64_t rowId = -1;
457         std::vector<NativeRdb::ValuesBucket> buckets;
458         for (auto &value : values) {
459             NativeRdb::ValuesBucket valuesBucket;
460             valuesBucket.PutString(NOTIFICATION_KEY, value.first);
461             valuesBucket.PutString(NOTIFICATION_VALUE, value.second);
462             buckets.emplace_back(valuesBucket);
463         }
464         ret = rdbStore_->BatchInsert(rowId, tableName, buckets);
465         if (ret == NativeRdb::E_SQLITE_CORRUPT) {
466             RestoreForMasterSlaver();
467         }
468         if (ret != NativeRdb::E_OK) {
469             ANS_LOGE("Insert batch operation failed, result: %{public}d.", ret);
470             message.ErrorCode(ret).Message("Insert batch operation failed.");
471             NotificationAnalyticsUtil::ReportModifyEvent(message);
472             return NativeRdb::E_ERROR;
473         }
474     }
475     SendUserDataSizeHisysevent();
476     return NativeRdb::E_OK;
477 }
478 
DeleteData(const std::string & key,const int32_t & userId)479 int32_t NotificationDataMgr::DeleteData(const std::string &key, const int32_t &userId)
480 {
481     ANS_LOGD("DeleteData start");
482     std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
483     std::reverse(operatedTables.begin(), operatedTables.end());
484     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
485     if (rdbStore_ == nullptr) {
486         ANS_LOGE("notification rdb is null");
487         return NativeRdb::E_ERROR;
488     }
489     int32_t ret = NativeRdb::E_OK;
490     int32_t rowId = -1;
491     for (auto tableName : operatedTables) {
492         ret = DeleteData(tableName, key, rowId);
493         if (ret != NativeRdb::E_OK) {
494             return ret;
495         }
496     }
497     return ret;
498 }
499 
DeleteData(const std::string tableName,const std::string key,int32_t & rowId)500 int32_t NotificationDataMgr::DeleteData(const std::string tableName, const std::string key, int32_t &rowId)
501 {
502     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
503     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_6);
504     absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
505     int32_t ret = rdbStore_->Delete(rowId, absRdbPredicates);
506     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
507         RestoreForMasterSlaver();
508     }
509     if (ret != NativeRdb::E_OK) {
510         ANS_LOGW("Delete operation failed from %{public}s, result: %{public}d, key=%{public}s.",
511             tableName.c_str(), ret, key.c_str());
512         message.ErrorCode(ret).Message("Delete operation failed.");
513         NotificationAnalyticsUtil::ReportModifyEvent(message);
514         return NativeRdb::E_ERROR;
515     }
516     return NativeRdb::E_OK;
517 }
518 
DeleteBatchData(const std::vector<std::string> & keys,const int32_t & userId)519 int32_t NotificationDataMgr::DeleteBatchData(const std::vector<std::string> &keys, const int32_t &userId)
520 {
521     ANS_LOGD("Delete Bathch Data start");
522     {
523         std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
524         std::reverse(operatedTables.begin(), operatedTables.end());
525         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
526         if (rdbStore_ == nullptr) {
527             ANS_LOGE("notification rdb is null");
528             return NativeRdb::E_ERROR;
529         }
530         std::vector<std::vector<std::string>> batchKeys;
531         auto start = keys.cbegin(), next = keys.cbegin(), end = keys.cend();
532         while (next != end) {
533             next = end - next < MAX_SIZE_PER_BATCH ? end : next + MAX_SIZE_PER_BATCH;
534             batchKeys.push_back(std::vector<std::string>(start, next));
535             start = next;
536         }
537 
538         int32_t rowId = -1;
539         for (auto tableName : operatedTables) {
540             NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
541             for (const auto &batchKey : batchKeys) {
542                 absRdbPredicates.In(NOTIFICATION_KEY, batchKey);
543                 int32_t ret = rdbStore_->Delete(rowId, absRdbPredicates);
544                 if (ret == NativeRdb::E_SQLITE_CORRUPT) {
545                     RestoreForMasterSlaver();
546                 }
547                 if (ret != NativeRdb::E_OK) {
548                     ANS_LOGW("Delete operation failed from %{public}s, result: %{public}d.",
549                         tableName.c_str(), ret);
550                     return NativeRdb::E_ERROR;
551                 }
552             }
553         }
554     }
555     return NativeRdb::E_OK;
556 }
557 
QueryData(const std::string & key,std::string & value,const int32_t & userId)558 int32_t NotificationDataMgr::QueryData(const std::string &key, std::string &value, const int32_t &userId)
559 {
560     ANS_LOGD("QueryData start");
561     std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
562     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
563     if (rdbStore_ == nullptr) {
564         ANS_LOGE("notification rdb is null");
565         return NativeRdb::E_ERROR;
566     }
567     int32_t ret = NativeRdb::E_OK;
568     for (auto tableName : operatedTables) {
569         ret = QueryData(tableName, key, value);
570         if (ret != NativeRdb::E_EMPTY_VALUES_BUCKET) {
571             return ret;
572         }
573     }
574     return ret;
575 }
576 
QueryData(const std::string tableName,const std::string key,std::string & value)577 int32_t NotificationDataMgr::QueryData(const std::string tableName, const std::string key, std::string &value)
578 {
579     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
580     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_2);
581     absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
582     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
583     if (absSharedResultSet == nullptr) {
584         ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
585         return NativeRdb::E_ERROR;
586     }
587 
588     int32_t ret = absSharedResultSet->GoToFirstRow();
589     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
590         RestoreForMasterSlaver();
591     }
592     if (ret != NativeRdb::E_OK) {
593         ANS_LOGW("GoToFirstRow failed from %{public}s table. It is empty!, key=%{public}s",
594             tableName.c_str(), key.c_str());
595             if (ret != NativeRdb::E_ROW_OUT_RANGE) {
596                 ANS_LOGW("GoToFirstRow failed, rdb error is %{public}d.", ret);
597                 message.ErrorCode(ret).Message("GoToFirstRow failed.");
598                 NotificationAnalyticsUtil::ReportModifyEvent(message);
599             }
600         absSharedResultSet->Close();
601         return NativeRdb::E_EMPTY_VALUES_BUCKET;
602     }
603     ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, value);
604     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
605         RestoreForMasterSlaver();
606     }
607     if (ret != NativeRdb::E_OK) {
608         ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
609         message.ErrorCode(ret).Message("GetString value failed.");
610         NotificationAnalyticsUtil::ReportModifyEvent(message);
611         absSharedResultSet->Close();
612         return NativeRdb::E_ERROR;
613     }
614     absSharedResultSet->Close();
615     return NativeRdb::E_OK;
616 }
617 
QueryData(const std::string & key,std::vector<uint8_t> & values,const int32_t & userId)618 int32_t NotificationDataMgr::QueryData(const std::string &key, std::vector<uint8_t> &values, const int32_t &userId)
619 {
620     std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
621     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
622     if (rdbStore_ == nullptr) {
623         ANS_LOGE("notification rdb is null");
624         return NativeRdb::E_ERROR;
625     }
626     int32_t ret = NativeRdb::E_OK;
627     for (auto tableName : operatedTables) {
628         ret = QueryData(tableName, key, values);
629         if (ret != NativeRdb::E_EMPTY_VALUES_BUCKET) {
630             return ret;
631         }
632     }
633     return ret;
634 }
635 
QueryData(const std::string tableName,const std::string key,std::vector<uint8_t> & value)636 int32_t NotificationDataMgr::QueryData(const std::string tableName, const std::string key, std::vector<uint8_t> &value)
637 {
638     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
639     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_3);
640     absRdbPredicates.EqualTo(NOTIFICATION_KEY, key);
641     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
642     if (absSharedResultSet == nullptr) {
643         ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
644         return NativeRdb::E_ERROR;
645     }
646 
647     int32_t ret = absSharedResultSet->GoToFirstRow();
648     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
649         RestoreForMasterSlaver();
650     }
651     if (ret != NativeRdb::E_OK) {
652         ANS_LOGW("GoToFirstRow failed from %{public}s table. It is empty!, key=%{public}s",
653             tableName.c_str(), key.c_str());
654         if (ret != NativeRdb::E_ROW_OUT_RANGE) {
655             ANS_LOGW("GoToFirstRow failed, rdb error is %{public}d.", ret);
656             message.ErrorCode(ret).Message("GoToFirstRow failed.");
657             NotificationAnalyticsUtil::ReportModifyEvent(message);
658         }
659         absSharedResultSet->Close();
660         return NativeRdb::E_EMPTY_VALUES_BUCKET;
661     }
662     ret = absSharedResultSet->GetBlob(NOTIFICATION_VALUE_INDEX, value);
663     if (ret != NativeRdb::E_OK) {
664         message.ErrorCode(ret).Message("GetString value failed.");
665         NotificationAnalyticsUtil::ReportModifyEvent(message);
666         ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
667         absSharedResultSet->Close();
668         return NativeRdb::E_ERROR;
669     }
670     absSharedResultSet->Close();
671 
672     return NativeRdb::E_OK;
673 }
674 
QueryDataBeginWithKey(const std::string & key,std::unordered_map<std::string,std::string> & values,const int32_t & userId)675 int32_t NotificationDataMgr::QueryDataBeginWithKey(
676     const std::string &key, std::unordered_map<std::string, std::string> &values, const int32_t &userId)
677 {
678     ANS_LOGD("QueryData BeginWithKey start");
679     std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
680     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
681     if (rdbStore_ == nullptr) {
682         ANS_LOGE("notification rdb is null");
683         return NativeRdb::E_ERROR;
684     }
685     int32_t ret = NativeRdb::E_OK;
686     for (auto tableName : operatedTables) {
687         ret = QueryDataBeginWithKey(tableName, key, values);
688         if (ret == NativeRdb::E_ERROR) {
689             return ret;
690         }
691     }
692     if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && values.empty()) {
693         return NativeRdb::E_EMPTY_VALUES_BUCKET;
694     }
695     return NativeRdb::E_OK;
696 }
697 
QueryDataBeginWithKey(const std::string tableName,const std::string key,std::unordered_map<std::string,std::string> & values)698 int32_t NotificationDataMgr::QueryDataBeginWithKey(
699     const std::string tableName, const std::string key, std::unordered_map<std::string, std::string> &values)
700 {
701     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
702     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_5);
703     absRdbPredicates.BeginsWith(NOTIFICATION_KEY, key);
704     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
705     if (absSharedResultSet == nullptr) {
706         ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
707         return NativeRdb::E_ERROR;
708     }
709 
710     int32_t ret = absSharedResultSet->GoToFirstRow();
711     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
712         RestoreForMasterSlaver();
713     }
714     if (ret != NativeRdb::E_OK) {
715         ANS_LOGD("GoToFirstRow failed from %{public}s table.It is empty!, key=%{public}s",
716             tableName.c_str(), key.c_str());
717         if (ret != NativeRdb::E_ROW_OUT_RANGE) {
718             ANS_LOGW("GoToFirstRow failed, rdb error is %{public}d.", ret);
719             message.ErrorCode(ret).Message("GoToFirstRow failed.");
720             NotificationAnalyticsUtil::ReportModifyEvent(message);
721         }
722         absSharedResultSet->Close();
723         return NativeRdb::E_EMPTY_VALUES_BUCKET;
724     }
725 
726     do {
727         std::string resultKey;
728         ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
729         if (ret != NativeRdb::E_OK) {
730             ANS_LOGE("Failed to GetString key from %{public}s table.", tableName.c_str());
731             message.ErrorCode(ret).Message("GetString key failed.");
732             NotificationAnalyticsUtil::ReportModifyEvent(message);
733             absSharedResultSet->Close();
734             return NativeRdb::E_ERROR;
735         }
736 
737         std::string resultValue;
738         ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
739         if (ret != NativeRdb::E_OK) {
740             ANS_LOGE("GetString value failed from %{public}s table", tableName.c_str());
741             message.ErrorCode(ret).Message("GetString value failed.");
742             NotificationAnalyticsUtil::ReportModifyEvent(message);
743             absSharedResultSet->Close();
744             return NativeRdb::E_ERROR;
745         }
746 
747         values.emplace(resultKey, resultValue);
748     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
749     absSharedResultSet->Close();
750 
751     return NativeRdb::E_OK;
752 }
753 
QueryDataContainsWithKey(const std::string & key,std::unordered_map<std::string,std::string> & values,const int32_t & userId)754 int32_t NotificationDataMgr::QueryDataContainsWithKey(
755     const std::string &key, std::unordered_map<std::string, std::string> &values, const int32_t &userId)
756 {
757     ANS_LOGD("QueryDataContainsWithKey start");
758     std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
759     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
760     if (rdbStore_ == nullptr) {
761         ANS_LOGE("notification rdb is null");
762         return NativeRdb::E_ERROR;
763     }
764     int32_t ret = NativeRdb::E_OK;
765     for (auto tableName : operatedTables) {
766         ret = QueryDataContainsWithKey(tableName, key, values);
767         if (ret == NativeRdb::E_ERROR) {
768             return ret;
769         }
770     }
771     if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && values.empty()) {
772         return NativeRdb::E_EMPTY_VALUES_BUCKET;
773     }
774     return NativeRdb::E_OK;
775 }
776 
QueryDataContainsWithKey(const std::string tableName,const std::string key,std::unordered_map<std::string,std::string> & values)777 int32_t NotificationDataMgr::QueryDataContainsWithKey(
778     const std::string tableName, const std::string key, std::unordered_map<std::string, std::string> &values)
779 {
780     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
781     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_9);
782     absRdbPredicates.Contains(NOTIFICATION_KEY, key);
783     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
784     if (absSharedResultSet == nullptr) {
785         ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
786         return NativeRdb::E_ERROR;
787     }
788     int32_t ret = absSharedResultSet->GoToFirstRow();
789     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
790         RestoreForMasterSlaver();
791     }
792     if (ret != NativeRdb::E_OK) {
793         ANS_LOGD("GoToFirstRow failed from %{public}s table.It is empty!, key=%{public}s",
794             tableName.c_str(), key.c_str());
795         if (ret != NativeRdb::E_ROW_OUT_RANGE) {
796             ANS_LOGW("GoToFirstRow failed, rdb error is %{public}d.", ret);
797             message.ErrorCode(ret).Message("GoToFirstRow failed.");
798             NotificationAnalyticsUtil::ReportModifyEvent(message);
799         }
800         absSharedResultSet->Close();
801         return NativeRdb::E_EMPTY_VALUES_BUCKET;
802     }
803     do {
804         std::string resultKey;
805         ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
806         if (ret != NativeRdb::E_OK) {
807             ANS_LOGE("Failed to GetString key from %{public}s table.", tableName.c_str());
808             message.ErrorCode(ret).Message("GetString key failed.");
809             NotificationAnalyticsUtil::ReportModifyEvent(message);
810             absSharedResultSet->Close();
811             return NativeRdb::E_ERROR;
812         }
813         std::string resultValue;
814         ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
815         if (ret != NativeRdb::E_OK) {
816             ANS_LOGE("GetString value failed from %{public}s table", tableName.c_str());
817             message.ErrorCode(ret).Message("GetString value failed.");
818             NotificationAnalyticsUtil::ReportModifyEvent(message);
819             absSharedResultSet->Close();
820             return NativeRdb::E_ERROR;
821         }
822         values.emplace(resultKey, resultValue);
823     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
824     absSharedResultSet->Close();
825     return NativeRdb::E_OK;
826 }
827 
QueryAllData(std::unordered_map<std::string,std::string> & datas,const int32_t & userId)828 int32_t NotificationDataMgr::QueryAllData(std::unordered_map<std::string, std::string> &datas, const int32_t &userId)
829 {
830     ANS_LOGD("QueryAllData start");
831     std::vector<std::string> operatedTables = GenerateOperatedTables(userId);
832     std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
833     if (rdbStore_ == nullptr) {
834         ANS_LOGE("notification rdb is null");
835         return NativeRdb::E_ERROR;
836     }
837     int32_t ret = NativeRdb::E_OK;
838     for (auto tableName : operatedTables) {
839         ret = QueryAllData(tableName,  datas);
840         if (ret == NativeRdb::E_ERROR) {
841             return ret;
842         }
843     }
844     if (ret == NativeRdb::E_EMPTY_VALUES_BUCKET && datas.empty()) {
845         return NativeRdb::E_EMPTY_VALUES_BUCKET;
846     }
847     return NativeRdb::E_OK;
848 }
849 
QueryAllData(const std::string tableName,std::unordered_map<std::string,std::string> & datas)850 int32_t NotificationDataMgr::QueryAllData(
851     const std::string tableName, std::unordered_map<std::string, std::string> &datas)
852 {
853     NativeRdb::AbsRdbPredicates absRdbPredicates(tableName);
854     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_4);
855     auto absSharedResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
856     if (absSharedResultSet == nullptr) {
857         ANS_LOGE("absSharedResultSet failed from %{public}s table.", tableName.c_str());
858         return NativeRdb::E_ERROR;
859     }
860 
861     int32_t ret = absSharedResultSet->GoToFirstRow();
862     if (ret == NativeRdb::E_SQLITE_CORRUPT) {
863         RestoreForMasterSlaver();
864     }
865     if (ret != NativeRdb::E_OK) {
866         ANS_LOGD("GoToFirstRow failed from %{public}s table. It is empty!", tableName.c_str());
867         if (ret != NativeRdb::E_ROW_OUT_RANGE) {
868             ANS_LOGW("GoToFirstRow failed, rdb error is %{public}d.", ret);
869             message.ErrorCode(ret).Message("GoToFirstRow failed.");
870             NotificationAnalyticsUtil::ReportModifyEvent(message);
871         }
872         absSharedResultSet->Close();
873         return NativeRdb::E_EMPTY_VALUES_BUCKET;
874     }
875 
876     do {
877         std::string resultKey;
878         ret = absSharedResultSet->GetString(NOTIFICATION_KEY_INDEX, resultKey);
879         if (ret != NativeRdb::E_OK) {
880             ANS_LOGE("GetString key failed from %{public}s table.", tableName.c_str());
881             message.ErrorCode(ret).Message("GetString key failed.");
882             NotificationAnalyticsUtil::ReportModifyEvent(message);
883             absSharedResultSet->Close();
884             return NativeRdb::E_ERROR;
885         }
886 
887         std::string resultValue;
888         ret = absSharedResultSet->GetString(NOTIFICATION_VALUE_INDEX, resultValue);
889         if (ret != NativeRdb::E_OK) {
890             ANS_LOGE("GetString value failed from %{public}s table.", tableName.c_str());
891             message.ErrorCode(ret).Message("GetString value failed.");
892             NotificationAnalyticsUtil::ReportModifyEvent(message);
893             absSharedResultSet->Close();
894             return NativeRdb::E_ERROR;
895         }
896 
897         datas.emplace(resultKey, resultValue);
898     } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
899     absSharedResultSet->Close();
900 
901     return NativeRdb::E_OK;
902 }
903 
DropUserTable(const int32_t userId)904 int32_t NotificationDataMgr::DropUserTable(const int32_t userId)
905 {
906     const char *keySpliter = "_";
907     std::stringstream stream;
908     stream << notificationRdbConfig_.tableName << keySpliter << userId;
909     std::string tableName = stream.str();
910     std::lock_guard<ffrt::mutex> lock(createdTableMutex_);
911     int32_t ret = NativeRdb::E_OK;
912     {
913         std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
914         if (rdbStore_ == nullptr) {
915             return NativeRdb::E_ERROR;
916         }
917         std::string dropTableSql = "DROP TABLE IF EXISTS " + tableName;
918         ret = rdbStore_->ExecuteSql(dropTableSql);
919     }
920     if (ret == NativeRdb::E_OK) {
921         createdTables_.erase(tableName);
922         ANS_LOGD("drop Table %{public}s succeed", tableName.c_str());
923         return ret;
924     }
925     return ret;
926 }
927 
GetUserTableName(const int32_t & userId,std::string & tableName)928 int32_t NotificationDataMgr::GetUserTableName(const int32_t &userId, std::string &tableName)
929 {
930     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_11, EventBranchId::BRANCH_1);
931     if (!OsAccountManagerHelper::IsSystemAccount(userId)) {
932         tableName = notificationRdbConfig_.tableName;
933         return NativeRdb::E_OK;
934     }
935 
936     const char *keySpliter = "_";
937     std::stringstream stream;
938     stream << notificationRdbConfig_.tableName << keySpliter << userId;
939     tableName = stream.str();
940     if (createdTables_.find(tableName) == createdTables_.end()) {
941         std::lock_guard<ffrt::mutex> lock(createdTableMutex_);
942         if (createdTables_.find(tableName) == createdTables_.end()) {
943             std::lock_guard<ffrt::mutex> lock(rdbStorePtrMutex_);
944             if (rdbStore_ == nullptr) {
945                 return NativeRdb::E_ERROR;
946             }
947             std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName
948                 + " (KEY TEXT NOT NULL PRIMARY KEY, VALUE TEXT NOT NULL);";
949             int32_t ret = rdbStore_->ExecuteSql(createTableSql);
950             if (ret != NativeRdb::E_OK) {
951                 ANS_LOGW("createTable %{public}s failed, code: %{public}d", tableName.c_str(), ret);
952                 message.ErrorCode(ret).Message("create table failed.");
953             NotificationAnalyticsUtil::ReportModifyEvent(message);
954                 return ret;
955             }
956             createdTables_.insert(tableName);
957             ANS_LOGD("createTable %{public}s succeed", tableName.c_str());
958             return NativeRdb::E_OK;
959         }
960     }
961     return NativeRdb::E_OK;
962 }
963 
GenerateOperatedTables(const int32_t & userId)964 std::vector<std::string> NotificationDataMgr::GenerateOperatedTables(const int32_t &userId)
965 {
966     std::vector<std::string> operatedTables;
967     if (OsAccountManagerHelper::IsSystemAccount(userId)) {
968         const char *keySpliter = "_";
969         std::stringstream stream;
970         stream << notificationRdbConfig_.tableName << keySpliter << userId;
971         std::string tableName = stream.str();
972         std::lock_guard<ffrt::mutex> lock(createdTableMutex_);
973         if (createdTables_.find(tableName) != createdTables_.end()) {
974             operatedTables.emplace_back(tableName);
975         }
976     }
977     operatedTables.emplace_back(notificationRdbConfig_.tableName);
978     return operatedTables;
979 }
980 
RestoreForMasterSlaver()981 int32_t NotificationDataMgr::RestoreForMasterSlaver()
982 {
983     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_10, EventBranchId::BRANCH_1)
984         .ErrorCode(NativeRdb::E_SQLITE_CORRUPT).Message("Rdb is corruped.");
985     NotificationAnalyticsUtil::ReportModifyEvent(message);
986     ANS_LOGI("RestoreForMasterSlaver start");
987     int32_t result =  rdbStore_->Restore("");
988     ANS_LOGI("RestoreForMasterSlaver result = %{public}d", result);
989     return result;
990 }
991 }
992 }