• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "reminder_store.h"
17 
18 #include <filesystem>
19 #include <sstream>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 
23 #include "ability_context.h"
24 #include "ans_log_wrapper.h"
25 #include "reminder_table.h"
26 #include "reminder_request_alarm.h"
27 #include "reminder_request_calendar.h"
28 #include "reminder_request_timer.h"
29 
30 namespace OHOS {
31 namespace Notification {
32 namespace {
33 const int32_t REMINDER_RDB_VERSION_V1 = 1;
34 const int32_t REMINDER_RDB_VERSION_V2 = 2;
35 const int32_t REMINDER_RDB_VERSION_V3 = 3;
36 const uint32_t REMINDER_RDB_VERSION = 4;
37 const int32_t STATE_FAIL = -1;
38 std::string g_sqlColumns;
39 }
40 
41 const int32_t ReminderStore::STATE_OK = 0;
42 const std::string ReminderStore::REMINDER_DB_DIR = "/data/service/el1/public/notification/";
43 const std::string ReminderStore::REMINDER_DB_NAME = "notification.db";
44 const std::string ReminderStore::REMINDER_DB_TABLE = "reminder";
45 
OnCreate(NativeRdb::RdbStore & store)46 int32_t ReminderStore::ReminderStoreDataCallBack::OnCreate(NativeRdb::RdbStore &store)
47 {
48     ANSR_LOGD("Create table.");
49     std::string CREATE_REMINDER_TABLE = "CREATE TABLE IF NOT EXISTS " + REMINDER_DB_TABLE + " ("
50         + ReminderTable::sqlOfAddColumns + ")";
51     ANSR_LOGD("CreateTable:%{public}s", CREATE_REMINDER_TABLE.c_str());
52     return store.ExecuteSql(CREATE_REMINDER_TABLE);
53 }
54 
OnUpgrade(NativeRdb::RdbStore & store,int32_t oldVersion,int32_t newVersion)55 int32_t ReminderStore::ReminderStoreDataCallBack::OnUpgrade(
56     NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion)
57 {
58     ANSR_LOGI("OnUpgrade oldVersion is %{public}d, newVersion is %{public}d", oldVersion, newVersion);
59     if (oldVersion < newVersion && newVersion == REMINDER_RDB_VERSION) {
60         if (oldVersion == REMINDER_RDB_VERSION_V1) {
61             AddRdbColum(store, "groupId", "TEXT");
62             AddRdbColum(store, "custom_ring_uri", "TEXT");
63             AddRdbColum(store, "snooze_slot_id", "INT");
64             AddRdbColum(store, "creator_bundle_name", "TEXT");
65         } else if (oldVersion == REMINDER_RDB_VERSION_V2) {
66             AddRdbColum(store, "custom_ring_uri", "TEXT");
67             AddRdbColum(store, "snooze_slot_id", "INT");
68             AddRdbColum(store, "creator_bundle_name", "TEXT");
69         } else if (oldVersion == REMINDER_RDB_VERSION_V3) {
70             AddRdbColum(store, "creator_bundle_name", "TEXT");
71         }
72     }
73     store.SetVersion(newVersion);
74     return NativeRdb::E_OK;
75 }
76 
Init()77 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Init()
78 {
79     ANSR_LOGD("Reminder store init.");
80     int32_t errCode(STATE_FAIL);
81 
82     if (access(REMINDER_DB_DIR.c_str(), F_OK) != 0) {
83         int createDir = mkdir(REMINDER_DB_DIR.c_str(), S_IRWXU);
84         if (createDir != 0) {
85             ANSR_LOGE("Failed to create directory %{public}s", REMINDER_DB_DIR.c_str());
86             return errCode;
87         }
88     }
89 
90     ReminderTable::InitDbColumns();
91     for (std::vector<std::string>::const_iterator it = ReminderTable::columns.begin();
92         it != ReminderTable::columns.end();
93         ++it) {
94         g_sqlColumns += *it + ",";
95     }
96     g_sqlColumns = g_sqlColumns.substr(0, g_sqlColumns.size() - 1);
97     ANSR_LOGD("ReminderStore g_sqlColumns =%{public}s", g_sqlColumns.c_str());
98 
99     std::string dbConfig = REMINDER_DB_DIR + REMINDER_DB_NAME;
100     NativeRdb::RdbStoreConfig config_(dbConfig);
101     config_.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
102     ReminderStoreDataCallBack rdbDataCallBack_;
103     rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config_, REMINDER_RDB_VERSION, rdbDataCallBack_, errCode);
104     if (rdbStore_ == nullptr) {
105         ANSR_LOGE("ReminderStore init fail, errCode %{public}d.", errCode);
106         return errCode;
107     }
108     return ReminderStore::InitData();
109 }
110 
InitData()111 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::InitData()
112 {
113     ANSR_LOGD("Reminder data init.");
114     if (rdbStore_ == nullptr) {
115         ANSR_LOGE("Rdb store is not initialized.");
116         return STATE_FAIL;
117     }
118     std::string deleteCondition = ReminderTable::IS_EXPIRED + " is true";
119     ReminderStore::Delete(deleteCondition);
120 
121     int32_t statusChangedRows = STATE_FAIL;
122     NativeRdb::ValuesBucket statusValues;
123     statusValues.PutInt(ReminderTable::STATE, ReminderRequest::REMINDER_STATUS_INACTIVE);
124     int32_t statusResult = rdbStore_->Update(statusChangedRows, REMINDER_DB_TABLE, statusValues);
125     ANSR_LOGD("Change status to inactive, changed rows: %{public}d.", statusChangedRows);
126     if (statusResult != NativeRdb::E_OK) {
127         ANSR_LOGE("Init data failed.");
128         return STATE_FAIL;
129     }
130 
131     int32_t activeChangedRows = STATE_FAIL;
132     NativeRdb::ValuesBucket activeValues;
133     activeValues.PutString(ReminderTable::IS_ACTIVE, "false");
134     std::string activeUpdateCondition = ReminderTable::IS_ACTIVE + " is true";
135     std::vector<std::string> activeWhereArgs;
136     int32_t activeResult = rdbStore_->Update(
137         activeChangedRows, REMINDER_DB_TABLE, activeValues, activeUpdateCondition, activeWhereArgs);
138     ANSR_LOGD("Change status isActive to false, changed rows: %{public}d.", activeChangedRows);
139     if (activeResult != NativeRdb::E_OK) {
140         ANSR_LOGE("Init data failed.");
141         return STATE_FAIL;
142     }
143 
144     int32_t scheduledChangedRows = STATE_FAIL;
145     NativeRdb::ValuesBucket scheduledValues;
146     scheduledValues.PutString(ReminderTable::HAS_SCHEDULED_TIMEOUT, "false");
147     std::string scheduledUpdateCondition = ReminderTable::HAS_SCHEDULED_TIMEOUT + " is true";
148     std::vector<std::string> scheduledWhereArgs;
149     int32_t scheduledResult = rdbStore_->Update(
150         scheduledChangedRows, REMINDER_DB_TABLE, scheduledValues, scheduledUpdateCondition, scheduledWhereArgs);
151     ANSR_LOGD("Change status has_ScheduledTimeout to false, changed rows: %{public}d.", scheduledChangedRows);
152     if (scheduledResult != NativeRdb::E_OK) {
153         ANSR_LOGE("Init data failed.");
154         return STATE_FAIL;
155     }
156     return ReminderStore::STATE_OK;
157 }
158 
Delete(int32_t reminderId)159 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Delete(int32_t reminderId)
160 {
161     std::string deleteCondition = ReminderTable ::REMINDER_ID
162         + " = " + std::to_string(reminderId);
163     return ReminderStore::Delete(deleteCondition);
164 }
165 
DeleteUser(int32_t userId)166 int32_t ReminderStore::DeleteUser(int32_t userId)
167 {
168     std::string deleteCondition = ReminderTable::USER_ID + " = " + std::to_string(userId);
169     return ReminderStore::Delete(deleteCondition);
170 }
171 
Delete(const std::string & pkg,int32_t userId)172 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Delete(const std::string &pkg, int32_t userId)
173 {
174     std::string deleteCondition = ReminderTable::PKG_NAME + " = \"" + pkg + "\" and "
175         + ReminderTable::USER_ID + " = " + std::to_string(userId);
176     return ReminderStore::Delete(deleteCondition);
177 }
178 
Delete(const std::string & deleteCondition)179 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Delete(const std::string &deleteCondition)
180 {
181     if (rdbStore_ == nullptr) {
182         ANSR_LOGE("Rdb store is not initialized.");
183         return STATE_FAIL;
184     }
185     int32_t deletedRows = STATE_FAIL;
186     std::vector<std::string> whereArgs;
187     int32_t result = rdbStore_->Delete(deletedRows, REMINDER_DB_TABLE, deleteCondition, whereArgs);
188     if (result != NativeRdb::E_OK) {
189         ANSR_LOGE("Delete operation failed, deleteConditon: %{public}s," \
190             "result: %{public}d.", deleteCondition.c_str(), result);
191     }
192     ANSR_LOGD("Delete operation done, deleteConditon: %{public}s," \
193         "deleted rows: %{public}d.", deleteCondition.c_str(), deletedRows);
194     return deletedRows;
195 }
196 
UpdateOrInsert(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption)197 int64_t ReminderStore::UpdateOrInsert(
198     const sptr<ReminderRequest> &reminder, const sptr<NotificationBundleOption> &bundleOption)
199 {
200     if (reminder->GetReminderType() == ReminderRequest::ReminderType::TIMER) {
201         ANSR_LOGI("Countdown not support persist.");
202         return STATE_FAIL;
203     }
204     int64_t isSuccess = STATE_FAIL;
205     if (rdbStore_ == nullptr) {
206         ANSR_LOGE("Rdb store is not initialized.");
207         return isSuccess;
208     }
209     if (bundleOption == nullptr) {
210         ANSR_LOGE("BundleOption is null.");
211         return isSuccess;
212     }
213     if (IsReminderExist(reminder)) {
214         isSuccess = Update(reminder, bundleOption);
215     } else {
216         isSuccess = Insert(reminder, bundleOption);
217     }
218     return isSuccess;
219 }
220 
Insert(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption)221 int64_t ReminderStore::Insert(
222     const sptr<ReminderRequest> &reminder, const sptr<NotificationBundleOption> &bundleOption)
223 {
224     if (rdbStore_ == nullptr) {
225         ANSR_LOGE("Rdb store is not initialized.");
226         return STATE_FAIL;
227     }
228     int64_t rowId = STATE_FAIL;
229     NativeRdb::ValuesBucket values;
230     ReminderStore::GenerateData(reminder, bundleOption, values);
231     int32_t result = rdbStore_->Insert(rowId, REMINDER_DB_TABLE, values);
232     if (result != NativeRdb::E_OK) {
233         ANSR_LOGE("Insert operation failed, result: %{public}d, reminderId=%{public}d.",
234             result, reminder->GetReminderId());
235         return result;
236     }
237     ANSR_LOGD("Insert successfully, reminderId=%{public}d.", reminder->GetReminderId());
238     return result;
239 }
240 
Update(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption)241 int64_t ReminderStore::Update(
242     const sptr<ReminderRequest> &reminder, const sptr<NotificationBundleOption> &bundleOption)
243 {
244     if (rdbStore_ == nullptr) {
245         ANSR_LOGE("Rdb store is not initialized.");
246         return STATE_FAIL;
247     }
248     int32_t changedRows = STATE_FAIL;
249     NativeRdb::ValuesBucket values;
250     ReminderStore::GenerateData(reminder, bundleOption, values);
251     std::string updateCondition = ReminderTable::REMINDER_ID
252         + " = " + std::to_string(reminder->GetReminderId());
253     std::vector<std::string> whereArgs;
254     int32_t result = rdbStore_->Update(changedRows, REMINDER_DB_TABLE, values, updateCondition, whereArgs);
255     if ((result != NativeRdb::E_OK) || (changedRows <= 0)) {
256         ANSR_LOGE("Update operation failed, result: %{public}d, updated rows: %{public}d, reminderId=%{public}d.",
257             result, changedRows, reminder->GetReminderId());
258         return result;
259     }
260     ANSR_LOGD("Update successfully, updated rows: %{public}d, reminderId=%{public}d.",
261         changedRows, reminder->GetReminderId());
262     return result;
263 }
264 
IsReminderExist(const sptr<ReminderRequest> & reminder)265 bool ReminderStore::IsReminderExist(const sptr<ReminderRequest> &reminder)
266 {
267     NativeRdb::AbsRdbPredicates absRdbPredicates(REMINDER_DB_TABLE);
268     absRdbPredicates.EqualTo(ReminderTable::REMINDER_ID, std::to_string(reminder->GetReminderId()));
269     auto queryResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
270     if (queryResultSet == nullptr) {
271         ANSR_LOGE("QueryResultSet is null.");
272         return false;
273     }
274     int32_t resultNum;
275     queryResultSet->GetRowCount(resultNum);
276     if (resultNum == 0) {
277         return false;
278     }
279     return true;
280 }
281 
Query(const std::string & queryCondition) const282 std::shared_ptr<NativeRdb::ResultSet> ReminderStore::Query(const std::string &queryCondition) const
283 {
284     if (rdbStore_ == nullptr) {
285         ANSR_LOGE("Rdb store is not initialized.");
286         return nullptr;
287     }
288     std::vector<std::string> whereArgs;
289     return rdbStore_->QuerySql(queryCondition, whereArgs);
290 }
291 
292 
GetMaxId()293 int32_t ReminderStore::GetMaxId()
294 {
295     if (rdbStore_ == nullptr) {
296         ANSR_LOGE("Rdb store is not initialized.");
297         return STATE_FAIL;
298     }
299     std::string queryCondition = "select " + ReminderTable::REMINDER_ID
300         + " from " + REMINDER_DB_TABLE + " order by "
301         + ReminderTable::REMINDER_ID + " desc";
302     auto queryResultSet = ReminderStore::Query(queryCondition);
303     if (queryResultSet == nullptr) {
304         ANSR_LOGE("QueryResultSet is null.");
305         return STATE_FAIL;
306     }
307     int32_t resultNum;
308     queryResultSet->GetRowCount(resultNum);
309     if (resultNum == 0) {
310         ANSR_LOGI("QueryResultSet is zero.");
311         return STATE_FAIL;
312     }
313     queryResultSet->GoToNextRow();
314     int32_t maxId = STATE_FAIL;
315     int32_t result = queryResultSet->GetInt(0, maxId);
316     if (result != NativeRdb::E_OK) {
317         ANSR_LOGE("Query operation failed, result %{public}d.", result);
318     }
319     ANSR_LOGD("MaxId: %{public}d.", maxId);
320     return maxId;
321 }
322 
GetAllValidReminders()323 __attribute__((no_sanitize("cfi"))) std::vector<sptr<ReminderRequest>> ReminderStore::GetAllValidReminders()
324 {
325     std::string sql = "select " + g_sqlColumns + " from " + REMINDER_DB_TABLE + " where "
326         + ReminderTable::IS_EXPIRED + " = 'false' order by "
327         + ReminderTable::TRIGGER_TIME + " asc";
328     ANSR_LOGD("GetAllValidReminders sql =%{public}s", sql.c_str());
329     return GetReminders(sql);
330 }
331 
GetReminders(const std::string & queryCondition)332 std::vector<sptr<ReminderRequest>> ReminderStore::GetReminders(const std::string &queryCondition)
333 {
334     std::vector<sptr<ReminderRequest>> reminders;
335     if (rdbStore_ == nullptr) {
336         ANSR_LOGE("Rdb store is not initialized.");
337         return reminders;
338     }
339     auto queryResultSet = Query(queryCondition);
340     if (queryResultSet == nullptr) {
341         return reminders;
342     }
343     bool isAtLastRow = false;
344     queryResultSet->IsAtLastRow(isAtLastRow);
345     while (!isAtLastRow) {
346         queryResultSet->GoToNextRow();
347         sptr<ReminderRequest> reminder = BuildReminder(queryResultSet);
348         if (reminder != nullptr) {
349             reminders.push_back(reminder);
350         }
351         queryResultSet->IsAtLastRow(isAtLastRow);
352     }
353     ANSR_LOGD("Size=%{public}zu", reminders.size());
354     return reminders;
355 }
356 
BuildReminder(const std::shared_ptr<NativeRdb::ResultSet> & resultSet)357 sptr<ReminderRequest> ReminderStore::BuildReminder(const std::shared_ptr<NativeRdb::ResultSet> &resultSet)
358 {
359     int32_t reminderType;
360     int32_t reminderId;
361     GetInt32Val(resultSet, ReminderTable::REMINDER_TYPE, reminderType);
362     GetInt32Val(resultSet, ReminderTable::REMINDER_ID, reminderId);
363 
364     sptr<ReminderRequest> reminder = nullptr;
365     switch (reminderType) {
366         case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
367             reminder = new (std::nothrow) ReminderRequestTimer(reminderId);
368             break;
369         }
370         case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
371             reminder = new (std::nothrow) ReminderRequestCalendar(reminderId);
372             break;
373         }
374         case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
375             reminder = new (std::nothrow) ReminderRequestAlarm(reminderId);
376             break;
377         }
378         default: {
379             ANSR_LOGE("ReminderType from database is error, reminderType %{public}d.", reminderType);
380             break;
381         }
382     }
383     if (reminder != nullptr) {
384         reminder->RecoverFromDb(resultSet);
385         ANSR_LOGI("BuildReminder success.");
386     } else {
387         ANSR_LOGW("BuildReminder fail.");
388     }
389     return reminder;
390 }
391 
GetBundleOption(const int32_t & reminderId,sptr<NotificationBundleOption> & bundleOption) const392 bool ReminderStore::GetBundleOption(const int32_t &reminderId, sptr<NotificationBundleOption> &bundleOption) const
393 {
394     if (rdbStore_ == nullptr) {
395         ANSR_LOGE("Rdb store is not initialized.");
396         return false;
397     }
398     NativeRdb::AbsRdbPredicates absRdbPredicates(REMINDER_DB_TABLE);
399     absRdbPredicates.EqualTo(ReminderTable ::REMINDER_ID, std::to_string(reminderId));
400     std::shared_ptr<OHOS::NativeRdb::ResultSet> queryResultSet =
401         rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
402     if (queryResultSet == nullptr) {
403         return false;
404     }
405     bool isAtLastRow = false;
406     queryResultSet->IsAtLastRow(isAtLastRow);
407     if (isAtLastRow) {
408         return false;
409     }
410     queryResultSet->GoToNextRow();
411     std::string pkgName;
412     GetStringVal(queryResultSet, ReminderTable ::PKG_NAME, pkgName);
413     int32_t uid;
414     GetInt32Val(queryResultSet, ReminderTable::UID, uid);
415     bundleOption->SetBundleName(pkgName);
416     bundleOption->SetUid(uid);
417     return true;
418 }
419 
GetInt32Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,int32_t & value)420 void ReminderStore::GetInt32Val(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
421     const std::string &name, int32_t &value)
422 {
423     int32_t columnIndex = -1;
424     resultSet->GetColumnIndex(name, columnIndex);
425     if (columnIndex == -1) {
426         ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
427         return;
428     }
429     resultSet->GetInt(columnIndex, value);
430 }
431 
GetInt64Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,int64_t & value)432 void ReminderStore::GetInt64Val(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
433     const std::string& name, int64_t& value)
434 {
435     int32_t columnIndex = -1;
436     resultSet->GetColumnIndex(name, columnIndex);
437     if (columnIndex == -1) {
438         ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
439         return;
440     }
441     resultSet->GetLong(columnIndex, value);
442 }
443 
GetStringVal(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,std::string & value)444 void ReminderStore::GetStringVal(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
445     const std::string &name, std::string &value)
446 {
447     int32_t columnIndex = -1;
448     resultSet->GetColumnIndex(name, columnIndex);
449     if (columnIndex == -1) {
450         ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
451         return;
452     }
453     resultSet->GetString(columnIndex, value);
454 }
455 
GenerateData(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption,NativeRdb::ValuesBucket & values) const456 void ReminderStore::GenerateData(const sptr<ReminderRequest> &reminder,
457     const sptr<NotificationBundleOption> &bundleOption, NativeRdb::ValuesBucket &values) const
458 {
459     ReminderRequest::AppendValuesBucket(reminder, bundleOption, values);
460     ReminderRequestCalendar::AppendValuesBucket(reminder, bundleOption, values);
461     ReminderRequestAlarm::AppendValuesBucket(reminder, bundleOption, values);
462 }
463 
AddRdbColum(NativeRdb::RdbStore & store,const std::string & columName,const std::string & type)464 void ReminderStore::AddRdbColum(NativeRdb::RdbStore &store, const std::string &columName, const std::string &type)
465 {
466     std::string sqlStr = "";
467     if (type == "TEXT") {
468         sqlStr = "ALTER TABLE " + REMINDER_DB_TABLE + " ADD " + columName + " " + type + " DEFAULT '';";
469     } else if (type == "INT") {
470         //3 is meaning others
471         sqlStr = "ALTER TABLE " + REMINDER_DB_TABLE + " ADD " + columName + " " + type + " DEFAULT 3;";
472     }
473     ANSR_LOGD("AddRdbColum sqlStr = %{public}s", sqlStr.c_str());
474     int errorCode = store.ExecuteSql(sqlStr);
475     if (errorCode != NativeRdb::E_OK) {
476         ANSR_LOGE("AddRdbColum error,errorCode is = %{public}d", errorCode);
477     };
478 }
479 }  // namespace Notification
480 }  // namespace OHOS
481