• 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_request_alarm.h"
26 #include "reminder_request_calendar.h"
27 #include "reminder_request_timer.h"
28 
29 namespace OHOS {
30 namespace Notification {
31 namespace {
32 const std::string REMINDER_DB_DIR = "/data/service/el1/public/notification/";
33 const std::string REMINDER_DB_NAME = "notification.db";
34 const std::string REMINDER_DB_TABLE = "reminder";
35 const uint32_t REMINDER_RDB_VERSION = 1;
36 const int32_t STATE_FAIL = -1;
37 std::vector<std::string> columns;
38 }
39 
40 const int32_t ReminderStore::STATE_OK = 0;
41 
OnCreate(NativeRdb::RdbStore & store)42 int32_t ReminderStore::ReminderStoreDataCallBack::OnCreate(NativeRdb::RdbStore &store)
43 {
44     ANSR_LOGD("Create table.");
45     std::string CREATE_REMINDER_TABLE = "CREATE TABLE IF NOT EXISTS " + REMINDER_DB_TABLE + " ("
46         + ReminderRequest::sqlOfAddColumns + ")";
47     ANSR_LOGD("CreateTable:%{public}s", CREATE_REMINDER_TABLE.c_str());
48     return store.ExecuteSql(CREATE_REMINDER_TABLE);
49 }
50 
OnUpgrade(NativeRdb::RdbStore & store,int32_t oldVersion,int32_t newVersion)51 int32_t ReminderStore::ReminderStoreDataCallBack::OnUpgrade(
52     NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion)
53 {
54     return NativeRdb::E_OK;
55 }
56 
Init()57 int32_t ReminderStore::Init()
58 {
59     ANSR_LOGD("Reminder store init.");
60     int32_t errCode(STATE_FAIL);
61 
62     if (access(REMINDER_DB_DIR.c_str(), F_OK) != 0) {
63         int createDir = mkdir(REMINDER_DB_DIR.c_str(), S_IRWXU);
64         if (createDir != 0) {
65             ANSR_LOGE("Failed to create directory %{public}s", REMINDER_DB_DIR.c_str());
66             return errCode;
67         }
68     }
69 
70     ReminderRequest::InitDbColumns();
71     ReminderRequestCalendar::InitDbColumns();
72     ReminderRequestAlarm::InitDbColumns();
73     columns.insert(columns.begin(),
74         ReminderRequest::columns.begin(), ReminderRequest::columns.end());
75 
76     std::string dbConfig = REMINDER_DB_DIR + REMINDER_DB_NAME;
77     NativeRdb::RdbStoreConfig config_(dbConfig);
78     ReminderStoreDataCallBack rdbDataCallBack_;
79     rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config_, REMINDER_RDB_VERSION, rdbDataCallBack_, errCode);
80     if (rdbStore_ == nullptr) {
81         ANSR_LOGE("ReminderStore init fail, errCode %{public}d.", errCode);
82         return errCode;
83     }
84     return ReminderStore::InitData();
85 }
86 
InitData()87 int32_t ReminderStore::InitData()
88 {
89     ANSR_LOGD("Reminder data init.");
90     if (rdbStore_ == nullptr) {
91         ANSR_LOGE("Rdb store is not initialized.");
92         return STATE_FAIL;
93     }
94     std::string deleteCondition = ReminderRequest::IS_EXPIRED + " is true";
95     ReminderStore::Delete(deleteCondition);
96 
97     int32_t statusChangedRows = STATE_FAIL;
98     NativeRdb::ValuesBucket statusValues;
99     statusValues.PutInt(ReminderRequest::STATE, ReminderRequest::REMINDER_STATUS_INACTIVE);
100     int32_t statusResult = rdbStore_->Update(statusChangedRows, REMINDER_DB_TABLE, statusValues);
101     ANSR_LOGD("Change status to inactive, changed rows: %{public}d.", statusChangedRows);
102     if (statusResult != NativeRdb::E_OK) {
103         ANSR_LOGE("Init data failed.");
104         return STATE_FAIL;
105     }
106 
107     int32_t activeChangedRows = STATE_FAIL;
108     NativeRdb::ValuesBucket activeValues;
109     activeValues.PutString(ReminderRequest::IS_ACTIVE, "false");
110     std::string activeUpdateCondition = ReminderRequest::IS_ACTIVE + " is true";
111     std::vector<std::string> activeWhereArgs;
112     int32_t activeResult = rdbStore_->Update(
113         activeChangedRows, REMINDER_DB_TABLE, activeValues, activeUpdateCondition, activeWhereArgs);
114     ANSR_LOGD("Change status isActive to false, changed rows: %{public}d.", activeChangedRows);
115     if (activeResult != NativeRdb::E_OK) {
116         ANSR_LOGE("Init data failed.");
117         return STATE_FAIL;
118     }
119 
120     int32_t scheduledChangedRows = STATE_FAIL;
121     NativeRdb::ValuesBucket scheduledValues;
122     scheduledValues.PutString(ReminderRequest::HAS_SCHEDULED_TIMEOUT, "false");
123     std::string scheduledUpdateCondition = ReminderRequest::HAS_SCHEDULED_TIMEOUT + " is true";
124     std::vector<std::string> scheduledWhereArgs;
125     int32_t scheduledResult = rdbStore_->Update(
126         scheduledChangedRows, REMINDER_DB_TABLE, scheduledValues, scheduledUpdateCondition, scheduledWhereArgs);
127     ANSR_LOGD("Change status has_ScheduledTimeout to false, changed rows: %{public}d.", scheduledChangedRows);
128     if (scheduledResult != NativeRdb::E_OK) {
129         ANSR_LOGE("Init data failed.");
130         return STATE_FAIL;
131     }
132     return ReminderStore::STATE_OK;
133 }
134 
Delete(int32_t reminderId)135 int32_t ReminderStore::Delete(int32_t reminderId)
136 {
137     std::string deleteCondition = ReminderRequest::REMINDER_ID
138         + " = " + std::to_string(reminderId);
139     return ReminderStore::Delete(deleteCondition);
140 }
141 
DeleteUser(int32_t userId)142 int32_t ReminderStore::DeleteUser(int32_t userId)
143 {
144     std::string deleteCondition = ReminderRequest::USER_ID + " = " + std::to_string(userId);
145     return ReminderStore::Delete(deleteCondition);
146 }
147 
Delete(const std::string & pkg,int32_t userId)148 int32_t ReminderStore::Delete(const std::string &pkg, int32_t userId)
149 {
150     std::string deleteCondition = ReminderRequest::PKG_NAME + " = \"" + pkg + "\" and "
151         + ReminderRequest::USER_ID + " = " + std::to_string(userId);
152     return ReminderStore::Delete(deleteCondition);
153 }
154 
Delete(const std::string & deleteCondition)155 int32_t ReminderStore::Delete(const std::string &deleteCondition)
156 {
157     if (rdbStore_ == nullptr) {
158         ANSR_LOGE("Rdb store is not initialized.");
159         return STATE_FAIL;
160     }
161     int32_t deletedRows = STATE_FAIL;
162     std::vector<std::string> whereArgs;
163     int32_t result = rdbStore_->Delete(deletedRows, REMINDER_DB_TABLE, deleteCondition, whereArgs);
164     if (result != NativeRdb::E_OK) {
165         ANSR_LOGE("Delete operation failed, deleteConditon: %{public}s," \
166             "result: %{public}d.", deleteCondition.c_str(), result);
167     }
168     ANSR_LOGD("Delete operation done, deleteConditon: %{public}s," \
169         "deleted rows: %{public}d.", deleteCondition.c_str(), deletedRows);
170     return deletedRows;
171 }
172 
UpdateOrInsert(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption)173 int64_t ReminderStore::UpdateOrInsert(
174     const sptr<ReminderRequest> &reminder, const sptr<NotificationBundleOption> &bundleOption)
175 {
176     if (reminder->GetReminderType() == ReminderRequest::ReminderType::TIMER) {
177         ANSR_LOGI("Countdown not support persist.");
178         return STATE_FAIL;
179     }
180     int64_t isSuccess = STATE_FAIL;
181     if (rdbStore_ == nullptr) {
182         ANSR_LOGE("Rdb store is not initialized.");
183         return isSuccess;
184     }
185     if (bundleOption == nullptr) {
186         ANSR_LOGE("BundleOption is null.");
187         return isSuccess;
188     }
189     if (IsReminderExist(reminder)) {
190         isSuccess = Update(reminder, bundleOption);
191     } else {
192         isSuccess = Insert(reminder, bundleOption);
193     }
194     return isSuccess;
195 }
196 
Insert(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption)197 int64_t ReminderStore::Insert(
198     const sptr<ReminderRequest> &reminder, const sptr<NotificationBundleOption> &bundleOption)
199 {
200     if (rdbStore_ == nullptr) {
201         ANSR_LOGE("Rdb store is not initialized.");
202         return STATE_FAIL;
203     }
204     int64_t rowId = STATE_FAIL;
205     NativeRdb::ValuesBucket values;
206     ReminderStore::GenerateData(reminder, bundleOption, values);
207     int32_t result = rdbStore_->Insert(rowId, REMINDER_DB_TABLE, values);
208     if (result != NativeRdb::E_OK) {
209         ANSR_LOGE("Insert operation failed, result: %{public}d, reminderId=%{public}d.",
210             result, reminder->GetReminderId());
211         return result;
212     }
213     ANSR_LOGD("Insert successfully, reminderId=%{public}d.", reminder->GetReminderId());
214     return result;
215 }
216 
Update(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption)217 int64_t ReminderStore::Update(
218     const sptr<ReminderRequest> &reminder, const sptr<NotificationBundleOption> &bundleOption)
219 {
220     if (rdbStore_ == nullptr) {
221         ANSR_LOGE("Rdb store is not initialized.");
222         return STATE_FAIL;
223     }
224     int32_t changedRows = STATE_FAIL;
225     NativeRdb::ValuesBucket values;
226     ReminderStore::GenerateData(reminder, bundleOption, values);
227     std::string updateCondition = ReminderRequest::REMINDER_ID
228         + " = " + std::to_string(reminder->GetReminderId());
229     std::vector<std::string> whereArgs;
230     int32_t result = rdbStore_->Update(changedRows, REMINDER_DB_TABLE, values, updateCondition, whereArgs);
231     if ((result != NativeRdb::E_OK) || (changedRows <= 0)) {
232         ANSR_LOGE("Update operation failed, result: %{public}d, updated rows: %{public}d, reminderId=%{public}d.",
233             result, changedRows, reminder->GetReminderId());
234         return result;
235     }
236     ANSR_LOGD("Update successfully, updated rows: %{public}d, reminderId=%{public}d.",
237         changedRows, reminder->GetReminderId());
238     return result;
239 }
240 
IsReminderExist(const sptr<ReminderRequest> & reminder)241 bool ReminderStore::IsReminderExist(const sptr<ReminderRequest> &reminder)
242 {
243     NativeRdb::AbsRdbPredicates absRdbPredicates(REMINDER_DB_TABLE);
244     absRdbPredicates.EqualTo(ReminderRequest::REMINDER_ID, std::to_string(reminder->GetReminderId()));
245     std::unique_ptr<NativeRdb::AbsSharedResultSet> queryResultSet = rdbStore_->Query(
246         absRdbPredicates, std::vector<std::string>());
247     if (queryResultSet == nullptr) {
248         ANSR_LOGE("QueryResultSet is null.");
249         return false;
250     }
251     int32_t resultNum;
252     queryResultSet->GetRowCount(resultNum);
253     if (resultNum == 0) {
254         return false;
255     }
256     return true;
257 }
258 
Query(const std::string & queryCondition) const259 std::shared_ptr<NativeRdb::AbsSharedResultSet> ReminderStore::Query(const std::string &queryCondition) const
260 {
261     std::unique_ptr<NativeRdb::AbsSharedResultSet> queryResultSet;
262     if (rdbStore_ == nullptr) {
263         ANSR_LOGE("Rdb store is not initialized.");
264         return queryResultSet;
265     }
266     std::vector<std::string> whereArgs;
267     queryResultSet = rdbStore_->QuerySql(queryCondition, whereArgs);
268     return queryResultSet;
269 }
270 
GetColumnIndex(const std::string & name)271 uint8_t ReminderStore::GetColumnIndex(const std::string& name)
272 {
273     uint8_t index = 0;
274     for (auto it = columns.begin(); it != columns.end(); ++it) {
275         if (name == (*it)) {
276             break;
277         }
278         index++;
279     }
280     return index;
281 }
282 
GetMaxId()283 int32_t ReminderStore::GetMaxId()
284 {
285     if (rdbStore_ == nullptr) {
286         ANSR_LOGE("Rdb store is not initialized.");
287         return STATE_FAIL;
288     }
289     std::string queryCondition = "select " + ReminderRequest::REMINDER_ID
290         + " from " + REMINDER_DB_TABLE + " order by "
291         + ReminderRequest::REMINDER_ID + " desc";
292     std::shared_ptr<NativeRdb::AbsSharedResultSet> queryResultSet = ReminderStore::Query(queryCondition);
293     if (queryResultSet == nullptr) {
294         ANSR_LOGE("QueryResultSet is null.");
295         return STATE_FAIL;
296     }
297     int32_t resultNum;
298     queryResultSet->GetRowCount(resultNum);
299     if (resultNum == 0) {
300         ANSR_LOGI("QueryResultSet is zero.");
301         return STATE_FAIL;
302     }
303     queryResultSet->GoToNextRow();
304     int32_t maxId = STATE_FAIL;
305     int32_t result = queryResultSet->GetInt(0, maxId);
306     if (result != NativeRdb::E_OK) {
307         ANSR_LOGE("Query operation failed, result %{public}d.", result);
308     }
309     ANSR_LOGD("MaxId: %{public}d.", maxId);
310     return maxId;
311 }
312 
GetAllValidReminders()313 std::vector<sptr<ReminderRequest>> ReminderStore::GetAllValidReminders()
314 {
315     std::string queryCondition = "select * from " + REMINDER_DB_TABLE + " where "
316         + ReminderRequest::IS_EXPIRED + " is false order by "
317         + ReminderRequest::TRIGGER_TIME + " asc";
318     ANSR_LOGD("Get all reminders");
319     return GetReminders(queryCondition);
320 }
321 
GetReminders(const std::string & queryCondition)322 std::vector<sptr<ReminderRequest>> ReminderStore::GetReminders(const std::string &queryCondition)
323 {
324     std::vector<sptr<ReminderRequest>> reminders;
325     if (rdbStore_ == nullptr) {
326         ANSR_LOGE("Rdb store is not initialized.");
327         return reminders;
328     }
329     std::shared_ptr<NativeRdb::AbsSharedResultSet> queryResultSet = Query(queryCondition);
330     if (queryResultSet == nullptr) {
331         return reminders;
332     }
333     bool isAtLastRow = false;
334     queryResultSet->IsAtLastRow(isAtLastRow);
335     while (!isAtLastRow) {
336         queryResultSet->GoToNextRow();
337         sptr<ReminderRequest> reminder;
338         reminder = BuildReminder(queryResultSet);
339         reminders.push_back(reminder);
340         queryResultSet->IsAtLastRow(isAtLastRow);
341     }
342     ANSR_LOGD("Size=%{public}zu", reminders.size());
343     return reminders;
344 }
345 
BuildReminder(const std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)346 sptr<ReminderRequest> ReminderStore::BuildReminder(const std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
347 {
348     int32_t reminderType;
349     int32_t reminderId;
350     resultSet->GetInt(ReminderStore::GetColumnIndex(ReminderRequest::REMINDER_TYPE), reminderType);
351     resultSet->GetInt(ReminderStore::GetColumnIndex(ReminderRequest::REMINDER_ID), reminderId);
352 
353     sptr<ReminderRequest> reminder = nullptr;
354     switch (reminderType) {
355         case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
356             reminder = new (std::nothrow) ReminderRequestTimer(reminderId);
357             break;
358         }
359         case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
360             reminder = new (std::nothrow) ReminderRequestCalendar(reminderId);
361             break;
362         }
363         case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
364             reminder = new (std::nothrow) ReminderRequestAlarm(reminderId);
365             break;
366         }
367         default: {
368             ANSR_LOGE("ReminderType from database is error, reminderType %{public}d.", reminderType);
369             break;
370         }
371     }
372     if (reminder != nullptr) {
373         reminder->RecoverFromDb(resultSet);
374         ANSR_LOGI("BuildReminder success.");
375     } else {
376         ANSR_LOGW("BuildReminder fail.");
377     }
378     return reminder;
379 }
380 
GetBundleOption(const int32_t & reminderId,sptr<NotificationBundleOption> & bundleOption) const381 bool ReminderStore::GetBundleOption(const int32_t &reminderId, sptr<NotificationBundleOption> &bundleOption) const
382 {
383     if (rdbStore_ == nullptr) {
384         ANSR_LOGE("Rdb store is not initialized.");
385         return false;
386     }
387     NativeRdb::AbsRdbPredicates absRdbPredicates(REMINDER_DB_TABLE);
388     absRdbPredicates.EqualTo(ReminderRequest::REMINDER_ID, std::to_string(reminderId));
389     std::shared_ptr<NativeRdb::AbsSharedResultSet> queryResultSet = rdbStore_->Query(
390         absRdbPredicates, std::vector<std::string>());
391     if (queryResultSet == nullptr) {
392         return false;
393     }
394     bool isAtLastRow = false;
395     queryResultSet->IsAtLastRow(isAtLastRow);
396     if (isAtLastRow) {
397         return false;
398     }
399     queryResultSet->GoToNextRow();
400     std::string pkgName;
401     GetStringVal(queryResultSet, ReminderRequest::PKG_NAME, pkgName);
402     int32_t uid;
403     GetInt32Val(queryResultSet, ReminderRequest::UID, uid);
404     bundleOption->SetBundleName(pkgName);
405     bundleOption->SetUid(uid);
406     return true;
407 }
408 
GetInt32Val(std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,const std::string & name,int32_t & value) const409 void ReminderStore::GetInt32Val(std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet,
410     const std::string &name, int32_t &value) const
411 {
412     int32_t columnIndex;
413     resultSet->GetColumnIndex(name, columnIndex);
414     resultSet->GetInt(columnIndex, value);
415 }
416 
GetStringVal(std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,const std::string & name,std::string & value) const417 void ReminderStore::GetStringVal(std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet,
418     const std::string &name, std::string &value) const
419 {
420     int32_t columnIndex;
421     resultSet->GetColumnIndex(name, columnIndex);
422     resultSet->GetString(columnIndex, value);
423 }
424 
GenerateData(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption,NativeRdb::ValuesBucket & values) const425 void ReminderStore::GenerateData(const sptr<ReminderRequest> &reminder,
426     const sptr<NotificationBundleOption> &bundleOption, NativeRdb::ValuesBucket &values) const
427 {
428     ReminderRequest::AppendValuesBucket(reminder, bundleOption, values);
429     ReminderRequestCalendar::AppendValuesBucket(reminder, bundleOption, values);
430     ReminderRequestAlarm::AppendValuesBucket(reminder, bundleOption, values);
431 }
432 }  // namespace Notification
433 }  // namespace OHOS
434