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 ¬ificationRdbConfig): 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 ¬ificationRdbConfig)
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 }