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