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 auto queryResultSet = rdbStore_->Query(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::ResultSet> ReminderStore::Query(const std::string &queryCondition) const
260 {
261 if (rdbStore_ == nullptr) {
262 ANSR_LOGE("Rdb store is not initialized.");
263 return nullptr;
264 }
265 std::vector<std::string> whereArgs;
266 return rdbStore_->QuerySql(queryCondition, whereArgs);
267 }
268
GetColumnIndex(const std::string & name)269 uint8_t ReminderStore::GetColumnIndex(const std::string& name)
270 {
271 uint8_t index = 0;
272 for (auto it = columns.begin(); it != columns.end(); ++it) {
273 if (name == (*it)) {
274 break;
275 }
276 index++;
277 }
278 return index;
279 }
280
GetMaxId()281 int32_t ReminderStore::GetMaxId()
282 {
283 if (rdbStore_ == nullptr) {
284 ANSR_LOGE("Rdb store is not initialized.");
285 return STATE_FAIL;
286 }
287 std::string queryCondition = "select " + ReminderRequest::REMINDER_ID
288 + " from " + REMINDER_DB_TABLE + " order by "
289 + ReminderRequest::REMINDER_ID + " desc";
290 auto queryResultSet = ReminderStore::Query(queryCondition);
291 if (queryResultSet == nullptr) {
292 ANSR_LOGE("QueryResultSet is null.");
293 return STATE_FAIL;
294 }
295 int32_t resultNum;
296 queryResultSet->GetRowCount(resultNum);
297 if (resultNum == 0) {
298 ANSR_LOGI("QueryResultSet is zero.");
299 return STATE_FAIL;
300 }
301 queryResultSet->GoToNextRow();
302 int32_t maxId = STATE_FAIL;
303 int32_t result = queryResultSet->GetInt(0, maxId);
304 if (result != NativeRdb::E_OK) {
305 ANSR_LOGE("Query operation failed, result %{public}d.", result);
306 }
307 ANSR_LOGD("MaxId: %{public}d.", maxId);
308 return maxId;
309 }
310
GetAllValidReminders()311 std::vector<sptr<ReminderRequest>> ReminderStore::GetAllValidReminders()
312 {
313 std::string queryCondition = "select * from " + REMINDER_DB_TABLE + " where "
314 + ReminderRequest::IS_EXPIRED + " is false order by "
315 + ReminderRequest::TRIGGER_TIME + " asc";
316 ANSR_LOGD("Get all reminders");
317 return GetReminders(queryCondition);
318 }
319
GetReminders(const std::string & queryCondition)320 std::vector<sptr<ReminderRequest>> ReminderStore::GetReminders(const std::string &queryCondition)
321 {
322 std::vector<sptr<ReminderRequest>> reminders;
323 if (rdbStore_ == nullptr) {
324 ANSR_LOGE("Rdb store is not initialized.");
325 return reminders;
326 }
327 auto queryResultSet = Query(queryCondition);
328 if (queryResultSet == nullptr) {
329 return reminders;
330 }
331 bool isAtLastRow = false;
332 queryResultSet->IsAtLastRow(isAtLastRow);
333 while (!isAtLastRow) {
334 queryResultSet->GoToNextRow();
335 sptr<ReminderRequest> reminder;
336 reminder = BuildReminder(queryResultSet);
337 reminders.push_back(reminder);
338 queryResultSet->IsAtLastRow(isAtLastRow);
339 }
340 ANSR_LOGD("Size=%{public}zu", reminders.size());
341 return reminders;
342 }
343
BuildReminder(const std::shared_ptr<NativeRdb::ResultSet> & resultSet)344 sptr<ReminderRequest> ReminderStore::BuildReminder(const std::shared_ptr<NativeRdb::ResultSet> &resultSet)
345 {
346 int32_t reminderType;
347 int32_t reminderId;
348 resultSet->GetInt(ReminderStore::GetColumnIndex(ReminderRequest::REMINDER_TYPE), reminderType);
349 resultSet->GetInt(ReminderStore::GetColumnIndex(ReminderRequest::REMINDER_ID), reminderId);
350
351 sptr<ReminderRequest> reminder = nullptr;
352 switch (reminderType) {
353 case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
354 reminder = new (std::nothrow) ReminderRequestTimer(reminderId);
355 break;
356 }
357 case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
358 reminder = new (std::nothrow) ReminderRequestCalendar(reminderId);
359 break;
360 }
361 case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
362 reminder = new (std::nothrow) ReminderRequestAlarm(reminderId);
363 break;
364 }
365 default: {
366 ANSR_LOGE("ReminderType from database is error, reminderType %{public}d.", reminderType);
367 break;
368 }
369 }
370 if (reminder != nullptr) {
371 reminder->RecoverFromDb(resultSet);
372 ANSR_LOGI("BuildReminder success.");
373 } else {
374 ANSR_LOGW("BuildReminder fail.");
375 }
376 return reminder;
377 }
378
GetBundleOption(const int32_t & reminderId,sptr<NotificationBundleOption> & bundleOption) const379 bool ReminderStore::GetBundleOption(const int32_t &reminderId, sptr<NotificationBundleOption> &bundleOption) const
380 {
381 if (rdbStore_ == nullptr) {
382 ANSR_LOGE("Rdb store is not initialized.");
383 return false;
384 }
385 NativeRdb::AbsRdbPredicates absRdbPredicates(REMINDER_DB_TABLE);
386 absRdbPredicates.EqualTo(ReminderRequest::REMINDER_ID, std::to_string(reminderId));
387 std::shared_ptr<OHOS::NativeRdb::ResultSet> queryResultSet =
388 rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
389 if (queryResultSet == nullptr) {
390 return false;
391 }
392 bool isAtLastRow = false;
393 queryResultSet->IsAtLastRow(isAtLastRow);
394 if (isAtLastRow) {
395 return false;
396 }
397 queryResultSet->GoToNextRow();
398 std::string pkgName;
399 GetStringVal(queryResultSet, ReminderRequest::PKG_NAME, pkgName);
400 int32_t uid;
401 GetInt32Val(queryResultSet, ReminderRequest::UID, uid);
402 bundleOption->SetBundleName(pkgName);
403 bundleOption->SetUid(uid);
404 return true;
405 }
406
GetInt32Val(std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,int32_t & value) const407 void ReminderStore::GetInt32Val(std::shared_ptr<NativeRdb::ResultSet> &resultSet,
408 const std::string &name, int32_t &value) const
409 {
410 int32_t columnIndex;
411 resultSet->GetColumnIndex(name, columnIndex);
412 resultSet->GetInt(columnIndex, value);
413 }
414
GetStringVal(std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,std::string & value) const415 void ReminderStore::GetStringVal(std::shared_ptr<NativeRdb::ResultSet> &resultSet,
416 const std::string &name, std::string &value) const
417 {
418 int32_t columnIndex;
419 resultSet->GetColumnIndex(name, columnIndex);
420 resultSet->GetString(columnIndex, value);
421 }
422
GenerateData(const sptr<ReminderRequest> & reminder,const sptr<NotificationBundleOption> & bundleOption,NativeRdb::ValuesBucket & values) const423 void ReminderStore::GenerateData(const sptr<ReminderRequest> &reminder,
424 const sptr<NotificationBundleOption> &bundleOption, NativeRdb::ValuesBucket &values) const
425 {
426 ReminderRequest::AppendValuesBucket(reminder, bundleOption, values);
427 ReminderRequestCalendar::AppendValuesBucket(reminder, bundleOption, values);
428 ReminderRequestAlarm::AppendValuesBucket(reminder, bundleOption, values);
429 }
430 } // namespace Notification
431 } // namespace OHOS
432