From bc7db1f5492e1dee5685d7709ccf8e368c9f2d43 Mon Sep 17 00:00:00 2001 From: linyunxuan Date: Wed, 2 Mar 2022 14:39:33 +0800 Subject: [PATCH 1/2] add database feature Signed-off-by: linyunxuan --- frameworks/ans/native/src/reminder_store.cpp | 434 ++++++++++++++++++ .../ans/native/include/reminder_store.h | 93 ++++ 2 files changed, 527 insertions(+) create mode 100644 frameworks/ans/native/src/reminder_store.cpp create mode 100644 interfaces/innerkits/ans/native/include/reminder_store.h diff --git a/frameworks/ans/native/src/reminder_store.cpp b/frameworks/ans/native/src/reminder_store.cpp new file mode 100644 index 000000000..b61e2a762 --- /dev/null +++ b/frameworks/ans/native/src/reminder_store.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reminder_store.h" + +#include +#include +#include +#include + +#include "ability_context.h" +#include "ans_log_wrapper.h" +#include "reminder_request_alarm.h" +#include "reminder_request_calendar.h" +#include "reminder_request_timer.h" + +namespace OHOS { +namespace Notification { +const std::string ReminderStore::REMINDER_DB_DIR = "/data/system_ce/ans_standard/"; +const std::string ReminderStore::REMINDER_DB_NAME = "reminder.db"; +const std::string ReminderStore::REMINDER_DB_TABLE = "reminder"; +const uint32_t ReminderStore::REMINDER_RDB_VERSION = 1; +const int32_t ReminderStore::STATE_FAIL = -1; +const int32_t ReminderStore::STATE_OK = 0; +const uint16_t ReminderStore::TIME_INTERVAL_FOR_DELETE = 1800; +const uint16_t ReminderStore::MILLI_SECONDS = 1000; +std::vector ReminderStore::COLUMNS; + +int32_t ReminderStore::ReminderStoreDataCallBack::OnCreate(NativeRdb::RdbStore &store) +{ + ANSR_LOGD("Create table."); + std::string CREATE_REMINDER_TABLE = "CREATE TABLE IF NOT EXISTS " + REMINDER_DB_TABLE + " (" + + ReminderRequest::Instance::SQL_ADD_COLUMNS + + ReminderRequestCalendar::Instance::SQL_ADD_COLUMNS + + ReminderRequestAlarm::Instance::SQL_ADD_COLUMNS + ")"; + ANSR_LOGD("~~~~createTable:%{public}s", CREATE_REMINDER_TABLE.c_str()); + return store.ExecuteSql(CREATE_REMINDER_TABLE); +} + +int32_t ReminderStore::ReminderStoreDataCallBack::OnUpgrade(NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion) +{ + return NativeRdb::E_OK; +} + +int32_t ReminderStore::Init() +{ + ANSR_LOGD("Reminder store init."); + int32_t errCode(STATE_FAIL); + + if (access(REMINDER_DB_DIR.c_str(), F_OK) != 0) { + int createDir = mkdir(REMINDER_DB_DIR.c_str(), S_IRWXU); + if (createDir != 0) { + ANSR_LOGE("Failed to create directory %{public}s", REMINDER_DB_DIR.c_str()); + return errCode; + } + } + + ReminderRequest::Instance::Init(); + ReminderRequestCalendar::Instance::Init(); + ReminderRequestAlarm::Instance::Init(); + ReminderStore::COLUMNS.insert(ReminderStore::COLUMNS.begin(), + ReminderRequestAlarm::Instance::COLUMNS.begin(), ReminderRequestAlarm::Instance::COLUMNS.end()); + ReminderStore::COLUMNS.insert(ReminderStore::COLUMNS.begin(), + ReminderRequestCalendar::Instance::COLUMNS.begin(), ReminderRequestCalendar::Instance::COLUMNS.end()); + ReminderStore::COLUMNS.insert(ReminderStore::COLUMNS.begin(), + ReminderRequest::Instance::COLUMNS.begin(), ReminderRequest::Instance::COLUMNS.end()); + + std::string dbConfig = ReminderStore::REMINDER_DB_DIR + ReminderStore::REMINDER_DB_NAME; + NativeRdb::RdbStoreConfig config_(dbConfig); + ReminderStoreDataCallBack rdbDataCallBack_; + rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config_, REMINDER_RDB_VERSION, rdbDataCallBack_, errCode); + if (rdbStore_ == nullptr) { + ANSR_LOGE("ReminderStore init fail, errCode %{public}d.", errCode); + return errCode; + } + return ReminderStore::InitData(); +} + +int32_t ReminderStore::InitData() +{ + ANSR_LOGD("Reminder data init."); + std::string deleteCondition = ReminderRequest::Instance::IS_EXPIRED + " is true"; + ReminderStore::Delete(deleteCondition); + + int32_t statusChangedRows = STATE_FAIL; + NativeRdb::ValuesBucket statusValues; + statusValues.PutInt(ReminderRequest::Instance::STATE, ReminderRequest::GetConstStateInactive()); + int32_t statusResult = rdbStore_->Update(statusChangedRows, REMINDER_DB_TABLE, statusValues); + ANSR_LOGD("Change status to inactive, changed rows: %{public}d.", statusChangedRows); + + int32_t activeChangedRows = STATE_FAIL; + NativeRdb::ValuesBucket activeValues; + activeValues.PutString(ReminderRequest::Instance::IS_ACTIVE, "false"); + std::string activeUpdateCondition = ReminderRequest::Instance::IS_ACTIVE + " is true"; + std::vector activeWhereArgs; + int32_t activeResult = rdbStore_->Update( + activeChangedRows, REMINDER_DB_TABLE, activeValues, activeUpdateCondition, activeWhereArgs); + ANSR_LOGD("Change status isActive to false, changed rows: %{public}d.", activeChangedRows); + + int32_t scheduledChangedRows = STATE_FAIL; + NativeRdb::ValuesBucket scheduledValues; + scheduledValues.PutString(ReminderRequest::Instance::HAS_SCHEDULED_TIMEOUT, "false"); + std::string scheduledUpdateCondition = ReminderRequest::Instance::HAS_SCHEDULED_TIMEOUT + " is true"; + std::vector scheduledWhereArgs; + int32_t scheduledResult = rdbStore_->Update( + scheduledChangedRows, REMINDER_DB_TABLE, scheduledValues, scheduledUpdateCondition, scheduledWhereArgs); + ANSR_LOGD("Change status has_ScheduledTimeout to false, changed rows: %{public}d.", scheduledChangedRows); + + if (statusResult != NativeRdb::E_OK || activeResult != NativeRdb::E_OK + || scheduledResult != NativeRdb::E_OK) { + ANSR_LOGE("Init data failed."); + return STATE_FAIL; + } + return STATE_OK; +} + +int32_t ReminderStore::Delete(int32_t reminderId) +{ + std::string deleteCondition = ReminderRequest::Instance::REMINDER_ID + + " = " + std::to_string(reminderId); + return ReminderStore::Delete(deleteCondition); +} + +int32_t ReminderStore::DeleteUser(int32_t userId) +{ + std::string deleteCondition = ReminderRequest::Instance::USER_ID + " = " + std::to_string(userId); + return ReminderStore::Delete(deleteCondition); +} + +int32_t ReminderStore::Delete(const std::string &pkg, int32_t userId) +{ + std::string deleteCondition = ReminderRequest::Instance::PKG_NAME + " = " + pkg + " and " + + ReminderRequest::Instance::USER_ID + " = " + std::to_string(userId); + return ReminderStore::Delete(deleteCondition); +} + +int32_t ReminderStore::Delete(const std::string &deleteCondition) +{ + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return STATE_FAIL; + } + int32_t deletedRows = STATE_FAIL; + std::vector whereArgs; + int32_t result = rdbStore_->Delete(deletedRows, REMINDER_DB_TABLE, deleteCondition, whereArgs); + if (result != NativeRdb::E_OK) { + ANSR_LOGE("Delete operation failed, deleteConditon: %{public}s," \ + "result: %{public}d.", deleteCondition.c_str(), result); + } + ANSR_LOGD("Delete operation done, deleteConditon: %{public}s," \ + "deleted rows: %{public}d.", deleteCondition.c_str(), deletedRows); + return deletedRows; +} + +int64_t ReminderStore::UpdateOrInsert( + const sptr &reminder, const sptr &bundleOption) +{ + if (reminder->GetReminderType() == ReminderRequest::ReminderType::TIMER) { + ANSR_LOGI("Countdown not support persist."); + return STATE_FAIL; + } + int64_t isSuccess = STATE_FAIL; + if (IsReminderExist(reminder)) { + isSuccess = ReminderStore::Update(reminder, bundleOption); + } else { + isSuccess = ReminderStore::Insert(reminder, bundleOption); + } + return isSuccess; +} + +int64_t ReminderStore::Insert( + const sptr &reminder, const sptr &bundleOption) +{ + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return STATE_FAIL; + } + if (bundleOption == nullptr) { + ANSR_LOGE("BundleOption is null."); + return STATE_FAIL; + } + int64_t rowId = STATE_FAIL; + NativeRdb::ValuesBucket values; + ReminderStore::GenerateData(reminder, bundleOption, values); + int32_t result = rdbStore_->Insert(rowId, REMINDER_DB_TABLE, values); + if (result != NativeRdb::E_OK) { + ANSR_LOGE("Insert operation failed, result: %{public}d, reminderId=%{public}d." + , result, reminder->GetReminderId()); + return result; + } + ANSR_LOGD("Insert successfully, reminderId=%{public}d.", reminder->GetReminderId()); + return result; +} + +int64_t ReminderStore::Update( + const sptr &reminder, const sptr &bundleOption) +{ + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return STATE_FAIL; + } + int32_t changedRows = STATE_FAIL; + NativeRdb::ValuesBucket values; + ReminderStore::GenerateData(reminder, bundleOption, values); + std::string updateCondition = ReminderRequest::Instance::REMINDER_ID + + " = " + std::to_string(reminder->GetReminderId()); + std::vector whereArgs; + int32_t result = rdbStore_->Update(changedRows, REMINDER_DB_TABLE, values, updateCondition, whereArgs); + if ((result != NativeRdb::E_OK) || (changedRows <= 0)) { + ANSR_LOGE("Update operation failed, result: %{public}d, updated rows: %{public}d, reminderId=%{public}d." + , result, changedRows, reminder->GetReminderId()); + return result; + } + ANSR_LOGD("Update successfully, updated rows: %{public}d, reminderId=%{public}d." + , changedRows, reminder->GetReminderId()); + return result; +} + +bool ReminderStore::IsReminderExist(const sptr &reminder) +{ + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return false; + } + std::string queryCondition = "select " + ReminderRequest::Instance::REMINDER_ID + + " from " + REMINDER_DB_TABLE + " where " + + ReminderRequest::Instance::REMINDER_ID + " = " + std::to_string(reminder->GetReminderId()); + std::vector whereArgs; + std::unique_ptr queryResultSet = rdbStore_->QuerySql(queryCondition, whereArgs); + if (queryResultSet == nullptr) { + ANSR_LOGE("QueryResultSet is null."); + return false; + } + int32_t resultNum; + queryResultSet->GetRowCount(resultNum); + if (resultNum == 0) { + return false; + } + return true; +} + +std::shared_ptr ReminderStore::Query(const std::string &queryCondition) const +{ + std::unique_ptr queryResultSet; + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return queryResultSet; + } + std::vector whereArgs; + queryResultSet = rdbStore_->QuerySql(queryCondition, whereArgs); + return queryResultSet; +} + +std::vector ReminderStore::GetRepeatInfo(int64_t repeatData, int32_t maxRepeatVal) +{ + std::vector repeatInfo; + for (int i = 1; i <= maxRepeatVal; i++) { + if ((repeatData & (1 << (i - 1))) > 0) { + repeatInfo.push_back(i); + } + } + return repeatInfo; +} + +uint8_t ReminderStore::GetColumnIndex(const std::string& name) +{ + uint8_t index = 0; + for (auto it = ReminderStore::COLUMNS.begin(); it != ReminderStore::COLUMNS.end(); ++it) { + if (name == (*it)) { + break; + } + index++; + } + return index; +} + +int32_t ReminderStore::GetMaxId() +{ + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return STATE_FAIL; + } + std::string queryCondition = "select " + ReminderRequest::Instance::REMINDER_ID + + " from " + REMINDER_DB_TABLE + " order by " + + ReminderRequest::Instance::REMINDER_ID + " desc"; + std::shared_ptr queryResultSet = ReminderStore::Query(queryCondition); + if (queryResultSet == nullptr) { + ANSR_LOGE("QueryResultSet is null."); + return STATE_FAIL; + } + int32_t resultNum; + queryResultSet->GetRowCount(resultNum); + if (resultNum == 0) { + ANSR_LOGI("QueryResultSet is zero."); + return STATE_FAIL; + } + queryResultSet->GoToNextRow(); + int32_t maxId = STATE_FAIL; + int32_t result = queryResultSet->GetInt(0, maxId); + if (result != NativeRdb::E_OK) { + ANSR_LOGE("Query operation failed, result %{public}d.", result); + } + ANSR_LOGD("MaxId: %{public}d.", maxId); + return maxId; +} + +std::vector> ReminderStore::GetAllValidReminders() +{ + std::string queryCondition = "select * from " + REMINDER_DB_TABLE + " where " + + ReminderRequest::Instance::IS_EXPIRED + " is false order by " + + ReminderRequest::Instance::TRIGGER_TIME + " asc"; + ANSR_LOGD("Get all reminders"); + return GetReminders(queryCondition); +} + +std::vector> ReminderStore::GetReminders(const std::string &queryCondition) +{ + std::vector> reminders; + if (rdbStore_ == nullptr) { + ANSR_LOGE("Rdb store is not initialized."); + return reminders; + } + std::shared_ptr queryResultSet = Query(queryCondition); + if (queryResultSet == nullptr) { + return reminders; + } + bool isAtLastRow = false; + queryResultSet->IsAtLastRow(isAtLastRow); + while(!isAtLastRow) { + queryResultSet->GoToNextRow(); + sptr reminder; + reminder = BuildReminder(queryResultSet); + reminders.push_back(reminder); + queryResultSet->IsAtLastRow(isAtLastRow); + } + ANSR_LOGD("Size=%{public}d", reminders.size()); + return reminders; +} + +sptr ReminderStore::BuildReminder(const std::shared_ptr &resultSet) +{ + int32_t reminderType; + int32_t reminderId; + resultSet->GetInt(ReminderStore::GetColumnIndex(ReminderRequest::Instance::REMINDER_TYPE), reminderType); + resultSet->GetInt(ReminderStore::GetColumnIndex(ReminderRequest::Instance::REMINDER_ID), reminderId); + + sptr reminder = nullptr; + switch (reminderType) { + case (static_cast(ReminderRequest::ReminderType::TIMER)): { + reminder = new ReminderRequestTimer(reminderId); + break; + } + case (static_cast(ReminderRequest::ReminderType::CALENDAR)): { + reminder = new ReminderRequestCalendar(reminderId); + break; + } + case (static_cast(ReminderRequest::ReminderType::ALARM)): { + reminder = new ReminderRequestAlarm(reminderId); + break; + } + default: { + ANSR_LOGE("ReminderType from database is error, reminderType %{public}d.", reminderType); + } + } + if (reminder != nullptr) { + reminder->RecoveryFromDb(resultSet); + ANSR_LOGI("BuildReminder success."); + } else { + ANSR_LOGW("BuildReminder fail."); + } + return reminder; +} + +bool ReminderStore::GetBundleOption(const int32_t &reminderId, sptr &bundleOption) const +{ + std::string queryCondition = "select " + ReminderRequest::Instance::PKG_NAME + ", " + + ReminderRequest::Instance::UID + " from " + REMINDER_DB_TABLE + " where " + + ReminderRequest::Instance::REMINDER_ID + "=" + std::to_string(reminderId); + std::shared_ptr queryResultSet = Query(queryCondition); + if (queryResultSet == nullptr) { + return false; + } + bool isAtLastRow = false; + queryResultSet->IsAtLastRow(isAtLastRow); + if (isAtLastRow) { + return false; + } + queryResultSet->GoToNextRow(); + std::string pkgName; + GetStringVal(queryResultSet, ReminderRequest::Instance::PKG_NAME, pkgName); + int32_t uid; + GetInt32Val(queryResultSet, ReminderRequest::Instance::UID, uid); + bundleOption->SetBundleName(pkgName); + bundleOption->SetUid(uid); + return true; +} + +void ReminderStore::GetInt32Val(std::shared_ptr &resultSet + , const std::string &name, int32_t &value) const +{ + int32_t columnIndex; + resultSet->GetColumnIndex(name, columnIndex); + resultSet->GetInt(columnIndex, value); // todo check outOf size +} + +void ReminderStore::GetStringVal(std::shared_ptr &resultSet + , const std::string &name, std::string &value) const +{ + int32_t columnIndex; + resultSet->GetColumnIndex(name, columnIndex); + resultSet->GetString(columnIndex, value); +} + +void ReminderStore::GenerateData(const sptr &reminder, + const sptr &bundleOption, NativeRdb::ValuesBucket &values) const +{ + ReminderRequest::AppendValuesBucket(reminder, bundleOption, values); + ReminderRequestCalendar::AppendValuesBucket(reminder, bundleOption, values); + ReminderRequestAlarm::AppendValuesBucket(reminder, bundleOption, values); +} +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/ans/native/include/reminder_store.h b/interfaces/innerkits/ans/native/include/reminder_store.h new file mode 100644 index 000000000..130e53e1b --- /dev/null +++ b/interfaces/innerkits/ans/native/include/reminder_store.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_ANS_STANDARD_INTERFACES_INNERKITS_ANS_NATIVE_INCLUDE_REMINDER_STORE_H +#define BASE_NOTIFICATION_ANS_STANDARD_INTERFACES_INNERKITS_ANS_NATIVE_INCLUDE_REMINDER_STORE_H + +#include + +#include "notification_bundle_option.h" +#include "reminder_request.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_store_config.h" + +namespace OHOS { +namespace Notification { +class ReminderStore { +public: + ReminderStore() {}; + virtual ~ReminderStore() {}; + int32_t Init(); + int32_t Delete(int32_t reminderId); + int32_t Delete(const std::string &pkg, int32_t userId); + int32_t DeleteUser(int32_t userId); + std::vector> GetAllValidReminders(); + bool GetBundleOption(const int32_t &reminderId, sptr &bundleOption) const; + int32_t GetMaxId(); + int64_t UpdateOrInsert(const sptr &reminder, const sptr &bundleOption); + static std::vector GetRepeatInfo(int64_t repeatData, int32_t maxRepeatVal); + static uint8_t GetColumnIndex(const std::string& name); + + static std::vector COLUMNS; + static const int32_t STATE_FAIL; + static const int32_t STATE_OK; + +private: + /** + * @brief Inits the data in database when system boot on or proxy process reboot on. + * + * 1. Deletes all the reminders which IS_EXPIRED is true. + * 2. Sets all the value of STATE to ReminderRequest::REMINDER_STATUS_INACTIVE + * 3. Sets all the value of IS_ACTIVE to false. + * 4. Sets all the value of HAS_SCHEDULED_TIMEOUT to false. + * + * @return int32_t result code. + */ + int32_t InitData(); + sptr BuildReminder(const std::shared_ptr &resultSet); + int32_t Delete(const std::string &deleteCondition); + void GetInt32Val(std::shared_ptr &resultSet + , const std::string &name, int32_t &value) const; + void GetStringVal(std::shared_ptr &resultSet + , const std::string &name, std::string &value) const; + std::vector> GetReminders(const std::string &queryCondition); + void GenerateData(const sptr &remindert, + const sptr &bundleOption, NativeRdb::ValuesBucket &values) const; + bool IsReminderExist(const sptr &reminder); + int64_t Insert(const sptr &reminder, const sptr &bundleOption); + std::shared_ptr Query(const std::string &queryCondition) const; + int64_t Update(const sptr &reminder, const sptr &bundleOption); + + static const std::string REMINDER_DB_DIR; + static const std::string REMINDER_DB_NAME; + static const std::string REMINDER_DB_TABLE; + static const uint32_t REMINDER_RDB_VERSION; + static const uint16_t TIME_INTERVAL_FOR_DELETE; + static const uint16_t MILLI_SECONDS; + +class ReminderStoreDataCallBack : public NativeRdb::RdbOpenCallback { +public: + int32_t OnCreate(NativeRdb::RdbStore &rdbStore) override; + int32_t OnUpgrade(NativeRdb::RdbStore &rdbStore, int32_t oldVersion, int32_t newVersion) override; +}; + +private: + std::shared_ptr rdbStore_ = nullptr; +}; +} // namespace Notification +} // namespace OHOS +#endif // BASE_NOTIFICATION_ANS_STANDARD_INTERFACES_INNERKITS_ANS_NATIVE_INCLUDE_REMINDER_STORE_H \ No newline at end of file -- Gitee From fe7bffcfe551813fc907bfba45a4492ee83e522b Mon Sep 17 00:00:00 2001 From: linyunxuan <10175495+lin-yunxuan@user.noreply.gitee.com> Date: Wed, 2 Mar 2022 07:16:49 +0000 Subject: [PATCH 2/2] update frameworks/ans/native/src/reminder_store.cpp. --- frameworks/ans/native/src/reminder_store.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/ans/native/src/reminder_store.cpp b/frameworks/ans/native/src/reminder_store.cpp index b61e2a762..a7ae4bc18 100644 --- a/frameworks/ans/native/src/reminder_store.cpp +++ b/frameworks/ans/native/src/reminder_store.cpp @@ -412,7 +412,7 @@ void ReminderStore::GetInt32Val(std::shared_ptr & { int32_t columnIndex; resultSet->GetColumnIndex(name, columnIndex); - resultSet->GetInt(columnIndex, value); // todo check outOf size + resultSet->GetInt(columnIndex, value); } void ReminderStore::GetStringVal(std::shared_ptr &resultSet -- Gitee