From 35086880332e21d1914cf7434250aa9b003426e5 Mon Sep 17 00:00:00 2001 From: gaojiaqi Date: Thu, 12 Dec 2024 14:03:18 +0800 Subject: [PATCH] update Signed-off-by: gaojiaqi --- frameworks/reminder/src/reminder_request.cpp | 107 ++++- .../src/reminder_request_calendar.cpp | 25 ++ .../reminder_request_calendar_test.cpp | 26 ++ .../test/unittest/reminder_request_test.cpp | 33 +- interfaces/inner_api/reminder_request.h | 18 + .../inner_api/reminder_request_calendar.h | 5 + ...advanced_notification_reminder_service.cpp | 1 + services/reminder/BUILD.gn | 1 + .../include/reminder_calendar_share_table.h | 81 ++++ .../reminder/include/reminder_data_manager.h | 50 ++- .../include/reminder_datashare_helper.h | 157 +++++++ .../reminder/src/reminder_data_manager.cpp | 190 ++++++-- .../src/reminder_data_manager_inner.cpp | 21 + .../src/reminder_datashare_helper.cpp | 414 ++++++++++++++++++ .../reminder/src/reminder_event_manager.cpp | 2 +- services/reminder/src/reminder_store.cpp | 3 + 16 files changed, 1066 insertions(+), 68 deletions(-) create mode 100644 services/reminder/include/reminder_calendar_share_table.h create mode 100644 services/reminder/include/reminder_datashare_helper.h create mode 100644 services/reminder/src/reminder_datashare_helper.cpp diff --git a/frameworks/reminder/src/reminder_request.cpp b/frameworks/reminder/src/reminder_request.cpp index 4b3bdf456..814c21ca9 100644 --- a/frameworks/reminder/src/reminder_request.cpp +++ b/frameworks/reminder/src/reminder_request.cpp @@ -72,6 +72,7 @@ const std::string ReminderRequest::REMINDER_EVENT_REMOVE_NOTIFICATION = "ohos.event.notification.reminder.REMOVE_NOTIFICATION"; const std::string ReminderRequest::REMINDER_EVENT_LOAD_REMINDER = "ohos.event.notification.reminder.LOAD_REMINDER"; const std::string ReminderRequest::PARAM_REMINDER_ID = "REMINDER_ID"; +const std::string ReminderRequest::PARAM_REMINDER_SHARE = "REMINDER_SHARE_FLAG"; const std::string ReminderRequest::SEP_BUTTON_SINGLE = ""; const std::string ReminderRequest::SEP_BUTTON_MULTI = ""; const std::string ReminderRequest::SEP_WANT_AGENT = ""; @@ -87,16 +88,20 @@ const uint16_t ReminderRequest::SECONDS_PER_HOUR = 3600; template void GetJsonValue(const nlohmann::json& root, const std::string& name, T& value) { + value = T(); + if (!root.contains(name)) { + return; + } using ValueType = std::remove_cv_t>; if constexpr (std::is_same_v) { - if (!root.contains(name) || !root[name].is_string()) { - value = T(); - return; + if (root[name].is_string()) { + value = root[name].get(); + } + } else if constexpr (std::is_same_v) { + if (root[name].is_number()) { + value = root[name].get(); } - value = root[name].get(); - return; } - value = T(); } inline static bool IsVaildButtonType(const std::string& type) @@ -377,8 +382,8 @@ bool ReminderRequest::HandleTimeZoneChange( void ReminderRequest::OnSameNotificationIdCovered() { - SetState(false, REMINDER_STATUS_ALERTING | REMINDER_STATUS_SHOWING | REMINDER_STATUS_SNOOZE, - "OnSameNotificationIdCovered"); + ANSR_LOGI("Reminder[%{public}d] same notification id covered.", reminderId_); + OnClose(true); } void ReminderRequest::OnShow(bool isPlaySoundOrVibration, bool isSysTimeChanged, bool allowToNotify) @@ -514,6 +519,52 @@ void ReminderRequest::RecoverActionButtonJsonMode(const std::string &jsonString) resource, buttonWantAgent, buttonDataShareUpdate); } +void ReminderRequest::DeserializeButtonInfoFromJson(const std::string& jsonString) +{ + if (jsonString.empty()) { + return; + } + if (!nlohmann::json::accept(jsonString)) { + ANSR_LOGW("Not a json string."); + return; + } + nlohmann::json root = nlohmann::json::parse(jsonString, nullptr, false); + if (root.is_discarded()) { + ANSR_LOGW("Parse json data failed."); + return; + } + if (!root.is_array()) { + return; + } + for (auto& button : root) { + int32_t type = static_cast(ActionButtonType::INVALID); + GetJsonValue(button, "type", type); + std::string title; + GetJsonValue(button, "title", title); + std::string resource; + GetJsonValue(button, "titleResource", resource); + std::string uri; + auto buttonWantAgent = std::make_shared(); + if (button.contains("wantAgent") && !button["wantAgent"].empty()) { + nlohmann::json wantAgent = button["wantAgent"]; + GetJsonValue(wantAgent, "pkgName", buttonWantAgent->pkgName); + GetJsonValue(wantAgent, "abilityName", buttonWantAgent->abilityName); + GetJsonValue(wantAgent, "uri", uri); + } + auto buttonDataShareUpdate = std::make_shared(); + if (button.contains("dataShareUpdate") && !button["dataShareUpdate"].empty()) { + nlohmann::json dataShareUpdate = button["dataShareUpdate"]; + GetJsonValue(dataShareUpdate, "uri", buttonDataShareUpdate->uri); + GetJsonValue(dataShareUpdate, "equalTo", buttonDataShareUpdate->equalTo); + GetJsonValue(dataShareUpdate, "valuesBucket", buttonDataShareUpdate->valuesBucket); + } + if (type == ActionButtonType::CUSTOM) { + customButtonUri_ = uri; + } + SetActionButton(title, ActionButtonType(type), resource, buttonWantAgent, buttonDataShareUpdate); + } +} + void ReminderRequest::DeserializeButtonInfo(const std::string& buttonInfoStr) { std::vector multiButton = StringSplit(buttonInfoStr, SEP_BUTTON_MULTI); @@ -576,31 +627,23 @@ void ReminderRequest::RecoverWantAgentByJson(const std::string& wantAgentInfo, c ANSR_LOGW("parse json data failed"); return; } - if (!root.contains("pkgName") || !root["pkgName"].is_string() || - !root.contains("abilityName") || !root["abilityName"].is_string() || - !root.contains("uri") || !root["uri"].is_string() || - !root.contains("parameters") || !root["parameters"].is_string()) { - return; - } - std::string pkgName = root.at("pkgName").get(); - std::string abilityName = root.at("abilityName").get(); - std::string uri = root.at("uri").get(); - std::string parameters = root.at("parameters").get(); switch (type) { case WANT_AGENT_FLAG: { auto wai = std::make_shared(); - wai->pkgName = pkgName; - wai->abilityName = abilityName; - wai->uri = uri; + GetJsonValue(root, "pkgName", wai->pkgName); + GetJsonValue(root, "abilityName", wai->abilityName); + GetJsonValue(root, "uri", wai->uri); + std::string parameters; + GetJsonValue(root, "parameters", parameters); wai->parameters = AAFwk::WantParamWrapper::ParseWantParams(parameters); SetWantAgentInfo(wai); break; } case MAX_WANT_AGENT_FLAG: { auto maxScreenWantAgentInfo = std::make_shared(); - maxScreenWantAgentInfo->pkgName = pkgName; - maxScreenWantAgentInfo->abilityName = abilityName; + GetJsonValue(root, "pkgName", maxScreenWantAgentInfo->pkgName); + GetJsonValue(root, "abilityName", maxScreenWantAgentInfo->abilityName); SetMaxScreenWantAgentInfo(maxScreenWantAgentInfo); break; } @@ -755,6 +798,11 @@ std::map R return actionButtonMap_; } +void ReminderRequest::SetActionButtons(const std::map& buttons) +{ + actionButtonMap_ = buttons; +} + std::string ReminderRequest::GetCreatorBundleName() const { return creatorBundleName_; @@ -932,6 +980,16 @@ std::string ReminderRequest::GetCustomButtonUri() const return customButtonUri_; } +bool ReminderRequest::IsShare() const +{ + return isShare_; +} + +void ReminderRequest::SetShare(const bool isShare) +{ + isShare_ = isShare; +} + void ReminderRequest::SetCustomRingUri(const std::string &uri) { customRingUri_ = uri; @@ -1450,6 +1508,7 @@ void ReminderRequest::AddActionButtons(NotificationRequest& notificationRequest, break; } want->SetParam(PARAM_REMINDER_ID, reminderId_); + want->SetParam(PARAM_REMINDER_SHARE, isShare_); std::vector> wants; wants.push_back(want); auto title = static_cast(button.second.title); @@ -1481,6 +1540,7 @@ void ReminderRequest::UpdateNotificationAddRemovalWantAgent(NotificationRequest& auto want = std::make_shared(); want->SetAction(REMINDER_EVENT_REMOVE_NOTIFICATION); want->SetParam(PARAM_REMINDER_ID, reminderId_); + want->SetParam(PARAM_REMINDER_SHARE, isShare_); std::vector> wants; wants.push_back(want); AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo( @@ -1508,6 +1568,7 @@ std::shared_ptr ReminderRequest::CreateWan auto want = std::make_shared(); want->SetAction(REMINDER_EVENT_CLICK_ALERT); want->SetParam(PARAM_REMINDER_ID, reminderId_); + want->SetParam(PARAM_REMINDER_SHARE, isShare_); std::vector> wantes; wantes.push_back(want); AbilityRuntime::WantAgent::WantAgentInfo wantInfo( diff --git a/frameworks/reminder/src/reminder_request_calendar.cpp b/frameworks/reminder/src/reminder_request_calendar.cpp index 00418b5f2..e32e2c7d6 100644 --- a/frameworks/reminder/src/reminder_request_calendar.cpp +++ b/frameworks/reminder/src/reminder_request_calendar.cpp @@ -796,6 +796,31 @@ uint64_t ReminderRequestCalendar::GetLastStartDateTime() const return lastStartDateTime_; } +void ReminderRequestCalendar::Copy(const sptr& other) +{ + if (other == nullptr || other->GetReminderType() != ReminderType::CALENDAR) { + return; + } + if (!IsShare() || !other->IsShare()) { + return; + } + SetNotificationId(other->GetNotificationId()); + SetTriggerTimeInMilli(other->GetTriggerTimeInMilli()); + SetSlotType(other->GetSlotType()); + SetCustomButtonUri(other->GetCustomButtonUri()); + SetTitle(other->GetTitle()); + SetContent(other->GetContent()); + SetActionButtons(other->GetActionButtons()); + SetWantAgentInfo(other->GetWantAgentInfo()); + SetAutoDeletedTime(other->GetAutoDeletedTime()); + ReminderRequestCalendar* calendar = static_cast(other.GetRefPtr()); + SetDateTime(calendar->GetDateTime()); + SetEndDateTime(calendar->GetEndDateTime()); + SetFirstDesignateYear(calendar->GetFirstDesignateYear()); + SetFirstDesignageMonth(calendar->GetFirstDesignageMonth()); + SetFirstDesignateDay(calendar->GetFirstDesignateDay()); +} + std::string ReminderRequestCalendar::SerializationRRule() { constexpr int32_t INDENT = -1; diff --git a/frameworks/reminder/test/unittest/reminder_request_calendar_test.cpp b/frameworks/reminder/test/unittest/reminder_request_calendar_test.cpp index 5cfdbf893..33a3216d7 100644 --- a/frameworks/reminder/test/unittest/reminder_request_calendar_test.cpp +++ b/frameworks/reminder/test/unittest/reminder_request_calendar_test.cpp @@ -1699,5 +1699,31 @@ HWTEST_F(ReminderRequestCalendarTest, InitTriggerTime_001, Function | SmallTest calendar.repeatDaysOfWeek_ = 1; EXPECT_EQ(calendar.InitTriggerTime(), true); } + +/** + * @tc.name: Copy_001 + * @tc.desc: Test Copy parameters. + * @tc.type: FUNC + * @tc.require:I9BM6I + */ +HWTEST_F(ReminderRequestCalendarTest, Copy_001, Function | SmallTest | Level1) +{ + sptr reminder1 = new ReminderRequestCalendar(1); + reminder1->SetTitle("test_reminder1"); + sptr reminder2 = new ReminderRequestCalendar(1); + reminder2->SetTitle("test_reminder2"); + + ReminderRequestCalendar* calendar = static_cast(reminder1.GetRefPtr()); + calendar->Copy(nullptr); + EXPECT_EQ(reminder1->GetTitle(), "test_reminder1"); + calendar->Copy(reminder2); + EXPECT_EQ(reminder1->GetTitle(), "test_reminder1"); + reminder1->SetShare(true); + calendar->Copy(reminder2); + EXPECT_EQ(reminder1->GetTitle(), "test_reminder1"); + reminder2->SetShare(true); + calendar->Copy(reminder2); + EXPECT_EQ(reminder1->GetTitle(), "test_reminder2"); +} } } \ No newline at end of file diff --git a/frameworks/reminder/test/unittest/reminder_request_test.cpp b/frameworks/reminder/test/unittest/reminder_request_test.cpp index 417530192..19339c748 100644 --- a/frameworks/reminder/test/unittest/reminder_request_test.cpp +++ b/frameworks/reminder/test/unittest/reminder_request_test.cpp @@ -1853,19 +1853,19 @@ HWTEST_F(ReminderRequestTest, RecoverWantAgentByJson_00001, Function | SmallTest jsonValue = R"({"pkgName":"com.example.myapplication","abilityName":"MainAbility"})"; rrc->RecoverWantAgentByJson(jsonValue, 0); - EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, ""); + EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, "MainAbility"); jsonValue = R"({"pkgName":"com.example.myapplication","abilityName":"MainAbility","uri":1})"; rrc->RecoverWantAgentByJson(jsonValue, 0); - EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, ""); + EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, "MainAbility"); jsonValue = R"({"pkgName":"com.example.myapplication","abilityName":"MainAbility","uri":""})"; rrc->RecoverWantAgentByJson(jsonValue, 0); - EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, ""); + EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, "MainAbility"); jsonValue = R"({"pkgName":"com.example.myapplication","abilityName":"MainAbility","uri":"","parameters":1})"; rrc->RecoverWantAgentByJson(jsonValue, 0); - EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, ""); + EXPECT_EQ(rrc->GetWantAgentInfo()->abilityName, "MainAbility"); jsonValue = R"({"pkgName":"com.example.myapplication","abilityName":"MainAbility","uri":"","parameters":""})"; rrc->RecoverWantAgentByJson(jsonValue, 0); @@ -2240,5 +2240,30 @@ HWTEST_F(ReminderRequestTest, SetMaxWantAgentStr_001, Function | SmallTest | Lev rrc->SetMaxWantAgentStr("@#$^%&*)(&&*^(@!#%$#$))"); EXPECT_EQ(rrc->GetMaxWantAgentStr(), "@#$^%&*)(&&*^(@!#%$#$))"); } + +/** + * @tc.name: DeserializeButtonInfoFromJson_001 + * @tc.desc: Test DeserializeButtonInfoFromJson parameters. + * @tc.type: FUNC + * @tc.require: issueI8CDH3 + */ +HWTEST_F(ReminderRequestTest, DeserializeButtonInfoFromJson_001, Function | SmallTest | Level1) +{ + ReminderRequest request(1); + request.DeserializeButtonInfoFromJson(""); + EXPECT_EQ(request.GetActionButtons().size(), 0); + request.DeserializeButtonInfoFromJson("{11"); + EXPECT_EQ(request.GetActionButtons().size(), 0); + request.DeserializeButtonInfoFromJson("{}"); + EXPECT_EQ(request.GetActionButtons().size(), 0); + request.DeserializeButtonInfoFromJson("[]"); + EXPECT_EQ(request.GetActionButtons().size(), 0); + request.DeserializeButtonInfoFromJson( + R"([{"titleResource":"join","title":"test","type":0,"wantAgent":{"pkgName":"","abilityName":"","uri":""}}])"); + EXPECT_EQ(request.GetActionButtons().size(), 1); + request.DeserializeButtonInfoFromJson( + R"([{"titleResource":"join","title":"test","type":2,"wantAgent":{"pkgName":"","abilityName":"","uri":""}}])"); + EXPECT_EQ(request.GetActionButtons().size(), 2); +} } } diff --git a/interfaces/inner_api/reminder_request.h b/interfaces/inner_api/reminder_request.h index 5374d67f5..d295c303f 100644 --- a/interfaces/inner_api/reminder_request.h +++ b/interfaces/inner_api/reminder_request.h @@ -310,6 +310,11 @@ public: */ std::map GetActionButtons() const; + /** + * @brief Set the reminder action buttons. + */ + void SetActionButtons(const std::map& buttons); + /** * @brief Obtains creator bundle name * @@ -848,6 +853,16 @@ public: */ std::string GetCustomButtonUri() const; + /** + * @brief Is the reminder from datashare. + */ + bool IsShare() const; + + /** + * @brief Set the reminder from datashare. + */ + void SetShare(const bool isShare); + /** * @brief Gets custom ring uri. * @@ -917,6 +932,7 @@ public: * Recover from the rdb. */ void DeserializeButtonInfo(const std::string& buttonInfoStr); + void DeserializeButtonInfoFromJson(const std::string& jsonString); static int32_t GetActualTime(const TimeTransferType &type, int32_t cTime); static int32_t GetCTime(const TimeTransferType &type, int32_t actualTime); @@ -971,6 +987,7 @@ public: static const std::string REMINDER_EVENT_REMOVE_NOTIFICATION; static const std::string REMINDER_EVENT_LOAD_REMINDER; static const std::string PARAM_REMINDER_ID; + static const std::string PARAM_REMINDER_SHARE; static const uint8_t REMINDER_STATUS_INACTIVE; static const uint8_t REMINDER_STATUS_ACTIVE; static const uint8_t REMINDER_STATUS_ALERTING; @@ -1088,6 +1105,7 @@ private: std::string title_ {}; std::string bundleName_ {}; bool isExpired_ {false}; + bool isShare_ {false}; uint8_t snoozeTimes_ {0}; uint8_t snoozeTimesDynamic_ {0}; uint8_t state_ {0}; diff --git a/interfaces/inner_api/reminder_request_calendar.h b/interfaces/inner_api/reminder_request_calendar.h index f117f14da..3dc1fb58e 100644 --- a/interfaces/inner_api/reminder_request_calendar.h +++ b/interfaces/inner_api/reminder_request_calendar.h @@ -319,6 +319,11 @@ public: ReminderRequestCalendar() : ReminderRequest(ReminderType::CALENDAR) {}; + /** + * @brief Copy datashare reminder + */ + void Copy(const sptr& other); + public: static constexpr uint8_t MAX_MONTHS_OF_YEAR = 12; static constexpr uint8_t MAX_DAYS_OF_MONTH = 31; diff --git a/services/ans/src/advanced_notification_reminder_service.cpp b/services/ans/src/advanced_notification_reminder_service.cpp index b20d405af..be5ccf0c4 100644 --- a/services/ans/src/advanced_notification_reminder_service.cpp +++ b/services/ans/src/advanced_notification_reminder_service.cpp @@ -120,6 +120,7 @@ ErrCode AdvancedNotificationService::SetNotificationRemindType(sptr + +namespace OHOS::Notification { +class ReminderCalendarShareTable { +public: + static constexpr const char* ID = "_id"; + static constexpr const char* EVENT_ID = "event_id"; + static constexpr const char* BEGIN = "begin"; + static constexpr const char* END = "end"; + static constexpr const char* ALARM_TIME = "alarmTime"; + static constexpr const char* STATE = "state"; + static constexpr const char* MINUTES = "minutes"; + static constexpr const char* TITLE = "title"; + static constexpr const char* CONTENT = "content"; + static constexpr const char* WANT_AGENT = "wantAgent"; + static constexpr const char* BUTTONS = "buttons"; + static constexpr const char* SLOT_TYPE = "slotType"; + static constexpr const char* KEEP_HEADSUP = "keepHeadsUp"; + + static constexpr const char* PROXY = "datashareproxy://com.huawei.hmos.calendardata/CalendarAlerts"; + static constexpr const char* NAME = "com.huawei.hmos.calendar"; + static constexpr const char* DATA_NAME = "com.huawei.hmos.calendardata"; + static constexpr const char* ENTRY = "ReminderCallbackExtAbility"; + + static constexpr const char* PARAM_CALLBACK_TYPE = "CallbackType"; + + /** + * @brief An alert begins in this state when it is first created. + */ + static constexpr int8_t STATE_SCHEDULED = 0; + /** + * @brief After a notification for an alert has been created it should be updated to fired. + */ + static constexpr int8_t STATE_FIRED = 1; + /** + * @brief Once the user has dismissed the notification the alert's state should be set to + * dismissed so it is not fired again. + */ + static constexpr int8_t STATE_DISMISSED = 2; + + /** + * @brief Start calendardata reason: Device start or restart complete. + */ + static constexpr int8_t START_BY_BOOT_COMPLETE = 0; + /** + * @brief Start calendardata reason: Time chage. + */ + static constexpr int8_t START_BY_TIME_CHANGE = 1; + /** + * @brief Start calendardata reason: Time zone chage. + */ + static constexpr int8_t START_BY_TIMEZONE_CHANGE = 2; + /** + * @brief Start calendardata reason: Timer. + */ + static constexpr int8_t START_BY_NORMAL = 3; + /** + * @brief Start calendardata reason: Language change. + */ + static constexpr int8_t START_BY_LANGUAGE_CHANGE = 4; +}; +} // namespace OHOS::Notification +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_REMINDER_INCLUDE_REMINDER_CALENDAR_SHARE_TABLE_H \ No newline at end of file diff --git a/services/reminder/include/reminder_data_manager.h b/services/reminder/include/reminder_data_manager.h index c91953098..a0023f946 100644 --- a/services/reminder/include/reminder_data_manager.h +++ b/services/reminder/include/reminder_data_manager.h @@ -222,6 +222,26 @@ public: */ void ClickReminder(const OHOS::EventFwk::Want &want); + /** + * @brief Load reminder event. + */ + void OnLoadReminderEvent(const EventFwk::Want& want); + + /** + * @brief datashare notify, share reminder insert. + */ + void OnDataShareInsert(); + + /** + * @brief datashare notify, share reminder update. + */ + void OnDataShareUpdate(const std::map>& reminders); + + /** + * @brief datashare notify, share reminder delete. + */ + void OnDataShareDelete(); + /** * Handle auto delete time */ @@ -263,9 +283,7 @@ public: int32_t QueryActiveReminderCount(); - void ReceiveLoadReminderEvent(); - - void StartReminderLoadTimer(); + void StartLoadTimer(); static constexpr uint8_t TIME_ZONE_CHANGE = 0; static constexpr uint8_t DATE_TIME_CHANGE = 1; @@ -401,9 +419,10 @@ private: * Find the reminder from reminderVector_ by reminder id. * * @param reminderId Indicates the reminder id. + * @param isShare Indicates the reminder datashare flag. * @return pointer of reminder request or nullptr. */ - sptr FindReminderRequestLocked(const int32_t &reminderId); + sptr FindReminderRequestLocked(const int32_t reminderId, const bool isShare); /** * Obtains the recent reminder which is not expired from reminder vector. @@ -502,8 +521,9 @@ private: * 2. cancels the notification. * * @param reminderId Indicates the reminder id. + * @param isShare Indicates the reminder datashare flag. */ - void RemoveReminderLocked(const int32_t &reminderId); + void RemoveReminderLocked(const int32_t reminderId, const bool isShare); /** * Resets timer status. @@ -639,7 +659,20 @@ private: */ void ReportSysEvent(const sptr& reminder); - int64_t CreateReminderLoadTimer(const sptr timer); + /** + * @brief Create load reminder timer. + */ + uint64_t CreateTimer(const sptr& timer); + + /** + * @brief Load reminder from datashare. + */ + void LoadShareReminders(); + + /** + * @brief Load reminder from datashare. + */ + void UpdateShareReminders(const std::map>& reminders); /** * Single instance. @@ -737,7 +770,10 @@ private: std::atomic saReadyFlag_{ 0 }; std::mutex timeLoadMutex_; - int32_t reminderLoadtimerId_ {0}; + uint64_t reminderLoadtimerId_ {0}; + + // Last time the calendardata was launched. + std::atomic lastStartTime_ {0}; }; } // namespace OHOS } // namespace Notification diff --git a/services/reminder/include/reminder_datashare_helper.h b/services/reminder/include/reminder_datashare_helper.h new file mode 100644 index 000000000..94023da07 --- /dev/null +++ b/services/reminder/include/reminder_datashare_helper.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024 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_DISTRIBUTED_NOTIFICATION_SERVICE_REMINDER_INCLUDE_REMINDER_DATASHARE_HELPER_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_REMINDER_INCLUDE_REMINDER_DATASHARE_HELPER_H + +#include "ffrt.h" +#include "reminder_request.h" +#include "datashare_helper.h" +#include "data_ability_observer_stub.h" + +#include +#include + +namespace OHOS::Notification { +class ReminderDataShareHelper { +public: + static ReminderDataShareHelper& GetInstance(); + + /** + * @brief Register datashare observer. + */ + bool RegisterObserver(); + + /** + * @brief UnRegister datashare observer. + */ + bool UnRegisterObserver(); + +public: + /** + * @brief Search for reminders from the current time to X minutes. + */ + bool Query(std::map>& reminders); + + /** + * @brief Update the reminder state. + * state is ReminderCalendarShareTable::STATE_* + */ + bool Update(const int32_t reminderId, const int32_t state); + + /** + * @brief Start calendar data extension. + * reason is ReminderCalendarShareTable::START_* + */ + void StartDataExtension(const int32_t reason); + +public: + /** + * @brief Set current user id. + */ + void SetUserId(const int32_t userId) + { + curUserId_ = userId; + } + + /** + * @brief Update calendar uid and calendar data uid. + */ + void UpdateCalendarUid(); + +public: + /** + * @brief When datashare notify OnChange, the change type is insert. + */ + void OnDataInsert(const DataShare::DataShareObserver::ChangeInfo& info); + + /** + * @brief When datashare notify OnChange, the change type is update. + */ + void OnDataUpdate(const DataShare::DataShareObserver::ChangeInfo& info); + + /** + * @brief When datashare notify OnChange, the change type is delete. + */ + void OnDataDelete(const DataShare::DataShareObserver::ChangeInfo& info); + +private: + /** + * @brief Build datasharehelper, need to release it after use, + * call ReleaseDataShareHelper. + */ + std::shared_ptr CreateDataShareHelper(); + bool ReleaseDataShareHelper(const std::shared_ptr& helper); + + /** + * @brief Get share table columns. + */ + std::vector GetColumns() const; + +private: + /** + * @brief Build ReminderRequest from DataShareResultSet. + */ + sptr CreateReminder(const std::shared_ptr& result); + + /** + * @brief Build ReminderRequest from ChangeInfo. + */ + std::map> CreateReminder( + const DataShare::DataShareObserver::ChangeInfo& info); + + /** + * @brief + */ + void InitBaseInfo(sptr& reminder); + +private: + // Singleton + ReminderDataShareHelper(); + ~ReminderDataShareHelper() = default; + + ReminderDataShareHelper(const ReminderDataShareHelper&) = delete; + ReminderDataShareHelper& operator=(const ReminderDataShareHelper&) = delete; + ReminderDataShareHelper(ReminderDataShareHelper&&) = delete; + ReminderDataShareHelper& operator=(ReminderDataShareHelper&&) = delete; + +private: + int32_t curUserId_ {0}; + int32_t uid_ {0}; // calendar + int32_t dataUid_ {0}; // calendardata + std::atomic insertTask_ {false}; + std::atomic deleteTask_ {false}; + std::atomic insertTime_ {0}; + std::atomic deleteTime_ {0}; + + std::mutex mutex_; // for observer_ + std::shared_ptr observer_; + + std::shared_ptr queue_; // for OnChange + +private: +class ReminderDataObserver : public DataShare::DataShareObserver { +public: + ReminderDataObserver() = default; + ~ReminderDataObserver() = default; + + /** + * @brief Notification of data changes. + */ + void OnChange(const ChangeInfo& info) override; +}; +}; +} // namespace OHOS::Notification +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_REMINDER_INCLUDE_REMINDER_DATASHARE_HELPER_H \ No newline at end of file diff --git a/services/reminder/src/reminder_data_manager.cpp b/services/reminder/src/reminder_data_manager.cpp index e66e30309..f2441d6d0 100644 --- a/services/reminder/src/reminder_data_manager.cpp +++ b/services/reminder/src/reminder_data_manager.cpp @@ -51,6 +51,8 @@ #endif #include "reminder_utils.h" #include "notification_helper.h" +#include "reminder_datashare_helper.h" +#include "reminder_calendar_share_table.h" namespace OHOS { namespace Notification { @@ -81,6 +83,13 @@ std::mutex ReminderDataManager::TIMER_MUTEX; std::mutex ReminderDataManager::ACTIVE_MUTEX; constexpr int32_t CONNECT_EXTENSION_INTERVAL = 100; constexpr int32_t CONNECT_EXTENSION_MAX_RETRY_TIMES = 3; +constexpr int64_t ONE_DAY_TIME = 24 * 60 * 60 * 1000; + +inline int64_t TimeDistance(int64_t first, int64_t last) +{ + return first > last ? first - last : last - first; +} + std::shared_ptr ReminderDataManager::serviceQueue_ = nullptr; ReminderDataManager::ReminderDataManager() = default; ReminderDataManager::~ReminderDataManager() = default; @@ -114,7 +123,7 @@ ErrCode ReminderDataManager::CancelReminder( { HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__); ANSR_LOGI("cancel reminder id: %{public}d", reminderId); - sptr reminder = FindReminderRequestLocked(reminderId); + sptr reminder = FindReminderRequestLocked(reminderId, false); if (reminder == nullptr) { ANSR_LOGW("Cancel reminder, not find the reminder"); return ERR_REMINDER_NOT_EXIST; @@ -136,7 +145,7 @@ ErrCode ReminderDataManager::CancelReminder( StopTimerLocked(TimerType::ALERTING_TIMER); } CancelNotification(reminder); - RemoveReminderLocked(reminderId); + RemoveReminderLocked(reminderId, false); StartRecentReminder(); return ERR_OK; } @@ -153,7 +162,7 @@ ErrCode ReminderDataManager::CancelAllReminders(const std::string& bundleName, sptr ReminderDataManager::CheckExcludeDateParam(const int32_t reminderId, const int32_t callingUid) { - sptr reminder = FindReminderRequestLocked(reminderId); + sptr reminder = FindReminderRequestLocked(reminderId, false); if (reminder == nullptr) { ANSR_LOGW("Check reminder failed, not find the reminder"); return nullptr; @@ -264,8 +273,12 @@ void ReminderDataManager::CancelRemindersImplLocked(const std::string& packageNa } CancelNotification(*vit); RemoveFromShowedReminders(*vit); - vit = reminderVector_.erase(vit); - totalCount_--; + if (!(*vit)->IsShare()) { + vit = reminderVector_.erase(vit); + totalCount_--; + } else { + ++vit; + } continue; } ++vit; @@ -355,7 +368,8 @@ void ReminderDataManager::AddToShowedReminders(const sptr &remi { std::lock_guard lock(ReminderDataManager::SHOW_MUTEX); for (auto it = showedReminderVector_.begin(); it != showedReminderVector_.end(); ++it) { - if (reminder->GetReminderId() == (*it)->GetReminderId()) { + if (reminder->GetReminderId() == (*it)->GetReminderId() && + reminder->IsShare() == (*it)->IsShare()) { ANSR_LOGD("Showed reminder is already exist"); return; } @@ -438,6 +452,7 @@ std::shared_ptr ReminderDataManager::CreateTimerInfo(TimerTyp want->SetAction(ReminderRequest::REMINDER_EVENT_ALARM_ALERT); sharedTimerInfo->SetAction(ReminderRequest::REMINDER_EVENT_ALARM_ALERT); want->SetParam(ReminderRequest::PARAM_REMINDER_ID, activeReminderId_); + want->SetParam(ReminderRequest::PARAM_REMINDER_SHARE, reminderRequest->IsShare()); break; } case (TimerType::ALERTING_TIMER): { @@ -448,6 +463,7 @@ std::shared_ptr ReminderDataManager::CreateTimerInfo(TimerTyp want->SetAction(ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT); sharedTimerInfo->SetAction(ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT); want->SetParam(ReminderRequest::PARAM_REMINDER_ID, alertingReminderId_); + want->SetParam(ReminderRequest::PARAM_REMINDER_SHARE, reminderRequest->IsShare()); break; } default: @@ -470,11 +486,11 @@ std::shared_ptr ReminderDataManager::CreateTimerInfo(TimerTyp return sharedTimerInfo; } -sptr ReminderDataManager::FindReminderRequestLocked(const int32_t &reminderId) +sptr ReminderDataManager::FindReminderRequestLocked(const int32_t reminderId, const bool isShare) { std::lock_guard lock(ReminderDataManager::MUTEX); for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { - if (reminderId == (*it)->GetReminderId()) { + if (reminderId == (*it)->GetReminderId() && isShare == (*it)->IsShare()) { return *it; } } @@ -490,7 +506,8 @@ bool ReminderDataManager::cmp(sptr &reminderRequest, sptr(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); - sptr reminder = FindReminderRequestLocked(reminderId); + bool isShare = want.GetBoolParam(ReminderRequest::PARAM_REMINDER_SHARE, false); + sptr reminder = FindReminderRequestLocked(reminderId, isShare); if (reminder == nullptr) { ANSR_LOGW("Invalid reminder id: %{public}d", reminderId); return; @@ -553,12 +570,16 @@ void ReminderDataManager::CloseReminder(const sptr &reminder, b StopSoundAndVibrationLocked(reminder); StopTimerLocked(TimerType::ALERTING_TIMER); } - reminder->OnClose(true); - RemoveFromShowedReminders(reminder); - store_->UpdateOrInsert(reminder); if (cancelNotification) { CancelNotification(reminder); } + reminder->OnClose(true); + RemoveFromShowedReminders(reminder); + if (reminder->IsShare()) { + ReminderDataShareHelper::GetInstance().Update(reminderId, ReminderCalendarShareTable::STATE_DISMISSED); + } else { + store_->UpdateOrInsert(reminder); + } } std::shared_ptr ReminderDataManager::GetInstance() @@ -575,7 +596,7 @@ std::shared_ptr ReminderDataManager::InitInstance() return REMINDER_DATA_MANAGER; } -void ReminderDataManager::StartReminderLoadTimer() +void ReminderDataManager::StartLoadTimer() { sptr timer = MiscServices::TimeServiceClient::GetInstance(); if (timer == nullptr) { @@ -584,14 +605,14 @@ void ReminderDataManager::StartReminderLoadTimer() } std::lock_guard locker(timeLoadMutex_); if (reminderLoadtimerId_ == 0) { - reminderLoadtimerId_ = CreateReminderLoadTimer(timer); + reminderLoadtimerId_ = CreateTimer(timer); } timer->StopTimer(reminderLoadtimerId_); uint64_t nowMilli = GetCurrentTime() + NEXT_LOAD_TIME; timer->StartTimer(reminderLoadtimerId_, nowMilli); } -int64_t ReminderDataManager::CreateReminderLoadTimer(const sptr timer) +uint64_t ReminderDataManager::CreateTimer(const sptr& timer); { auto sharedTimerInfo = std::make_shared(); sharedTimerInfo->SetRepeat(true); @@ -791,6 +812,13 @@ void ReminderDataManager::RefreshRemindersDueToSysTimeChange(uint8_t type) StopTimerLocked(TimerType::TRIGGER_TIMER); } LoadReminderFromDb(); + int64_t now = GetCurrentTime(); + LoadShareReminders(); + if (TimeDistance(now, lastStartTime_) > ONE_DAY_TIME) { + lastStartTime_ = now; + ReminderDataShareHelper::GetInstance().StartDataExtension(type == TIME_ZONE_CHANGE ? + ReminderCalendarShareTable::START_BY_TIMEZONE_CHANGE : ReminderCalendarShareTable::START_BY_TIME_CHANGE); + } std::vector> showImmediately; std::vector> extensionReminders; RefreshRemindersLocked(type, showImmediately, extensionReminders); @@ -802,7 +830,8 @@ void ReminderDataManager::RefreshRemindersDueToSysTimeChange(uint8_t type) void ReminderDataManager::TerminateAlerting(const OHOS::EventFwk::Want &want) { int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); - sptr reminder = FindReminderRequestLocked(reminderId); + bool isShare = want.GetBoolParam(ReminderRequest::PARAM_REMINDER_SHARE, false); + sptr reminder = FindReminderRequestLocked(reminderId, isShare); if (reminder == nullptr) { ANSR_LOGE("Invalid reminder id: %{public}d", reminderId); return; @@ -900,11 +929,12 @@ bool ReminderDataManager::ShouldAlert(const sptr &reminder) con void ReminderDataManager::ShowActiveReminder(const EventFwk::Want &want) { int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); + bool isShare = want.GetBoolParam(ReminderRequest::PARAM_REMINDER_SHARE, false); ANSR_LOGI("Begin to show reminder(reminderId=%{public}d)", reminderId); if (reminderId == activeReminderId_) { ResetStates(TimerType::TRIGGER_TIMER); } - sptr reminder = FindReminderRequestLocked(reminderId); + sptr reminder = FindReminderRequestLocked(reminderId, isShare); if (reminder == nullptr) { ANSR_LOGW("Invalid reminder id: %{public}d", reminderId); return; @@ -1045,6 +1075,7 @@ void ReminderDataManager::ShowReminder(const sptr &reminder, co ANSR_LOGD("Show the reminder(Play sound: %{public}d), %{public}s", static_cast(isNeedToPlaySound), reminder->Dump().c_str()); int32_t reminderId = reminder->GetReminderId(); + bool isShare = reminder->IsShare(); if (!IsAllowedNotify(reminder)) { ANSR_LOGE("Not allow to notify."); reminder->OnShow(false, isSysTimeChanged, false); @@ -1075,6 +1106,9 @@ void ReminderDataManager::ShowReminder(const sptr &reminder, co } } HandleSameNotificationIdShowing(reminder); + if (isShare) { + ReminderDataShareHelper::GetInstance().Update(reminderId, ReminderCalendarShareTable::STATE_FIRED); + } } store_->UpdateOrInsert(reminder); @@ -1086,7 +1120,8 @@ void ReminderDataManager::ShowReminder(const sptr &reminder, co void ReminderDataManager::SnoozeReminder(const OHOS::EventFwk::Want &want) { int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); - sptr reminder = FindReminderRequestLocked(reminderId); + bool isShare = want.GetBoolParam(ReminderRequest::PARAM_REMINDER_SHARE, false); + sptr reminder = FindReminderRequestLocked(reminderId, isShare); if (reminder == nullptr) { ANSR_LOGW("Invalid reminder id: %{public}d", reminderId); return; @@ -1234,9 +1269,11 @@ sptr ReminderDataManager::GetRecentReminder() } int32_t reminderId = (*it)->GetReminderId(); ANSR_LOGD("Containers(vector) remove. reminderId=%{public}d", reminderId); + if (!(*it)->IsShare()) { + totalCount_--; + store_->Delete(reminderId); + } it = reminderVector_.erase(it); - totalCount_--; - store_->Delete(reminderId); } return nullptr; } @@ -1294,12 +1331,13 @@ void ReminderDataManager::HandleSameNotificationIdShowing(const sptrGetNotificationId(); + bool isShare = reminder->IsShare(); ANSR_LOGD("HandleSameNotificationIdShowing notificationId=%{public}d", notificationId); int32_t curReminderId = reminder->GetReminderId(); for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { int32_t tmpId = (*it)->GetReminderId(); - if (tmpId == curReminderId) { + if (tmpId == curReminderId && (*it)->IsShare() == isShare) { continue; } if (!(*it)->IsShowing()) { @@ -1311,7 +1349,11 @@ void ReminderDataManager::HandleSameNotificationIdShowing(const sptrOnSameNotificationIdCovered(); RemoveFromShowedReminders(*it); - store_->UpdateOrInsert((*it)); + if ((*it)->IsShare()) { + ReminderDataShareHelper::GetInstance().Update(tmpId, ReminderCalendarShareTable::STATE_DISMISSED); + } else { + store_->UpdateOrInsert((*it)); + } } } } @@ -1344,13 +1386,19 @@ void ReminderDataManager::Init() InitServiceHandler(); LoadReminderFromDb(); InitUserId(); + ReminderDataShareHelper::GetInstance().SetUserId(currentUserId_); + ReminderDataShareHelper::GetInstance().UpdateCalendarUid(); + ReminderDataShareHelper::GetInstance().RegisterObserver(); + LoadShareReminders(); + lastStartTime_ = GetCurrentTime(); + ReminderDataShareHelper::GetInstance().StartDataExtension(ReminderCalendarShareTable::START_BY_BOOT_COMPLETE); std::vector> immediatelyReminders; std::vector> extensionReminders; CheckReminderTime(immediatelyReminders, extensionReminders); HandleImmediatelyShow(immediatelyReminders, false); HandleExtensionReminder(extensionReminders); StartRecentReminder(); - StartReminderLoadTimer(); + StartLoadTimer(); isReminderAgentReady_ = true; ANSR_LOGD("ReminderAgent is ready."); } @@ -1465,16 +1513,23 @@ bool ReminderDataManager::IsBelongToSameApp(const int32_t uidSrc, return result; } -void ReminderDataManager::ReceiveLoadReminderEvent() +void ReminderDataManager::OnLoadReminderEvent() { LoadReminderFromDb(); + LoadShareReminders(); + int64_t now = static_cast(ReminderRequest::GetCurrentTimeInMilli()); + if (TimeDistance(now, lastStartTime_) > ONE_DAY_TIME) { + lastStartTime_ = now; + ReminderDataShareHelper::GetInstance().StartDataExtension(ReminderCalendarShareTable::START_BY_NORMAL); + } StartRecentReminder(); + StartLoadTimer(); } void ReminderDataManager::LoadReminderFromDb() { - std::lock_guard lock(ReminderDataManager::MUTEX); std::vector> existReminders = store_->GetHalfHourReminders(); + std::lock_guard lock(ReminderDataManager::MUTEX); reminderVector_ = existReminders; totalCount_ = static_cast(reminderVector_.size()); ReminderRequest::GLOBAL_ID = store_->GetMaxId() + 1; @@ -1591,7 +1646,8 @@ void ReminderDataManager::RemoveFromShowedReminders(const sptr { std::lock_guard lock(ReminderDataManager::SHOW_MUTEX); for (auto it = showedReminderVector_.begin(); it != showedReminderVector_.end(); ++it) { - if ((*it)->GetReminderId() == reminder->GetReminderId()) { + if ((*it)->GetReminderId() == reminder->GetReminderId() && + (*it)->IsShare() == reminder->IsShare()) { ANSR_LOGD("Containers(shownVector) remove. reminderId=%{public}d", reminder->GetReminderId()); showedReminderVector_.erase(it); break; @@ -1615,15 +1671,17 @@ void ReminderDataManager::RefreshRemindersLocked(uint8_t type, } } -void ReminderDataManager::RemoveReminderLocked(const int32_t &reminderId) +void ReminderDataManager::RemoveReminderLocked(const int32_t reminderId, bool isShare) { std::lock_guard lock(ReminderDataManager::MUTEX); for (auto it = reminderVector_.begin(); it != reminderVector_.end();) { - if (reminderId == (*it)->GetReminderId()) { + if (reminderId == (*it)->GetReminderId() && isShare == (*it)->IsShare()) { ANSR_LOGD("Containers(vector) remove. reminderId=%{public}d", reminderId); it = reminderVector_.erase(it); - totalCount_--; - store_->Delete(reminderId); + if (!isShare) { + totalCount_--; + store_->Delete(reminderId); + } break; } else { ++it; @@ -1780,7 +1838,8 @@ void ReminderDataManager::ResetStates(TimerType type) void ReminderDataManager::HandleCustomButtonClick(const OHOS::EventFwk::Want &want) { int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); - sptr reminder = FindReminderRequestLocked(reminderId); + bool isShare = want.GetBoolParam(ReminderRequest::PARAM_REMINDER_SHARE, false); + sptr reminder = FindReminderRequestLocked(reminderId, isShare); if (reminder == nullptr) { ANSR_LOGE("Invalid reminder id: %{public}d", reminderId); return; @@ -1812,13 +1871,14 @@ void ReminderDataManager::HandleCustomButtonClick(const OHOS::EventFwk::Want &wa void ReminderDataManager::ClickReminder(const OHOS::EventFwk::Want &want) { int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); + bool isShare = want.GetBoolParam(ReminderRequest::PARAM_REMINDER_SHARE, false); ANSR_LOGI("click reminder[%{public}d] start", reminderId); - sptr reminder = FindReminderRequestLocked(reminderId); + sptr reminder = FindReminderRequestLocked(reminderId, isShare); if (reminder == nullptr) { ANSR_LOGW("Invalid reminder id: %{public}d", reminderId); return; } - CloseReminder(reminder, true); + CloseReminder(reminder, false); StartRecentReminder(); auto wantInfo = reminder->GetWantAgentInfo(); @@ -1910,6 +1970,9 @@ void ReminderDataManager::OnLanguageChanged() { std::lock_guard lock(ReminderDataManager::MUTEX); for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if ((*it)->IsShare()) { + continue; + } reminders[(*it)->GetUid()].push_back((*it)); } } @@ -1922,9 +1985,13 @@ void ReminderDataManager::OnLanguageChanged() showedReminder = showedReminderVector_; } for (auto it = showedReminder.begin(); it != showedReminder.end(); ++it) { + if ((*it)->IsShare()) { + continue; + } std::lock_guard lock(ReminderDataManager::MUTEX); ShowReminder((*it), false, false, false, false); } + ReminderDataShareHelper::GetInstance().StartDataExtension(ReminderCalendarShareTable::START_BY_LANGUAGE_CHANGE); ANSR_LOGI("System language config changed end."); } @@ -2000,5 +2067,62 @@ int32_t ReminderDataManager::QueryActiveReminderCount() { return store_->QueryActiveReminderCount(); } + +void ReminderDataManager::LoadShareReminders() +{ + std::map> reminders; + ReminderDataShareHelper::GetInstance().Query(reminders); + std::lock_guard locker(ReminderDataManager::MUTEX); + for (auto it = reminderVector_.begin(); it != reminderVector_.end();) { + if (!(*it)->IsShare()) { + ++it; + continue; + } + int32_t reminderId = (*it)->GetReminderId(); + if (reminders.find(reminderId) != reminders.end()) { + // only exit + reminders.erase(reminderId); + ++it; + continue; + } + // already remove + if ((*it)->IsShowing()) { + CloseReminder(*it, true); + } + if (activeReminderId_ == reminderId) { + { + std::lock_guard locker(ReminderDataManager::ACTIVE_MUTEX); + activeReminder_->OnStop(); + } + StopTimerLocked(TimerType::TRIGGER_TIMER); + } + it = reminderVector_.erase(it); + reminders.erase(reminderId); + } + // new reminder + for (auto& each : reminders) { + reminderVector_.push_back(each.second); + } +} + +void ReminderDataManager::UpdateShareReminders(const std::map>& reminders) +{ + std::lock_guard locker(ReminderDataManager::MUTEX); + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if (!(*it)->IsShare() || (*it)->GetReminderType() != ReminderRequest::ReminderType::CALENDAR) { + continue; + } + int32_t reminderId = (*it)->GetReminderId(); + auto iter = reminders.find(reminderId); + if (iter == reminders.end()) { + continue; + } + ReminderRequestCalendar* calendar = static_cast((*it).GetRefPtr()); + calendar->Copy(iter->second); + if ((*it)->IsShowing()) { + ShowReminder((*it), false, false, false, false); + } + } +} } } diff --git a/services/reminder/src/reminder_data_manager_inner.cpp b/services/reminder/src/reminder_data_manager_inner.cpp index 261f4d745..761d4b645 100644 --- a/services/reminder/src/reminder_data_manager_inner.cpp +++ b/services/reminder/src/reminder_data_manager_inner.cpp @@ -162,5 +162,26 @@ void ReminderDataManager::ReportSysEvent(const sptr& reminder) "RING_TIME", ringTime); #endif } + +void ReminderDataManager::OnDataShareInsert() +{ + LoadShareReminders(); + std::vector> immediatelyReminders; + std::vector> extensionReminders; + CheckReminderTime(immediatelyReminders, extensionReminders); + HandleImmediatelyShow(immediatelyReminders, false); + StartRecentReminder(); +} + +void ReminderDataManager::OnDataShareUpdate(const std::map>& reminders) +{ + UpdateShareReminders(reminders); +} + +void ReminderDataManager::OnDataShareDelete() +{ + LoadShareReminders(); + StartRecentReminder(); +} } } diff --git a/services/reminder/src/reminder_datashare_helper.cpp b/services/reminder/src/reminder_datashare_helper.cpp new file mode 100644 index 000000000..ca9435924 --- /dev/null +++ b/services/reminder/src/reminder_datashare_helper.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2024 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_datashare_helper.h" + +#include "ans_log_wrapper.h" +#include "iservice_registry.h" +#include "reminder_calendar_share_table.h" +#include "system_ability_definition.h" +#include "reminder_request_calendar.h" +#include "reminder_data_manager.h" +#include "ability_manager_client.h" +#include "in_process_call_wrapper.h" +#include "bundle_manager_helper.h" + +namespace OHOS::Notification { +namespace { +constexpr int64_t DURATION_ONE_HOUR = 60 * 60 * 1000; // 1h, millisecond +constexpr int64_t DURATION_DELAY_TASK = 1 * 1000 * 1000; // 1s, microsecond +constexpr int64_t CYCLE_DATASHARE_TASK = 1; // 1s +} + +template +void GetRdbValue(const std::shared_ptr& resultSet, + const std::string& name, T& value) +{ + value = T(); + int32_t columnIndex = -1; + resultSet->GetColumnIndex(name, columnIndex); + if (columnIndex == -1) { + ANSR_LOGE("the column %{public}s does not exsit.", name.c_str()); + return; + } + + if constexpr (std::is_same_v) { + resultSet->GetString(columnIndex, value); + } else if constexpr (std::is_same_v) { + resultSet->GetLong(columnIndex, value); + } else if constexpr (std::is_same_v) { + int64_t t = 0; + resultSet->GetLong(columnIndex, t); + value = static_cast(t); + } else if constexpr (std::is_integral_v) { + int32_t t = 0; + resultSet->GetInt(columnIndex, t); + value = static_cast(t); + } +} + +ReminderDataShareHelper& ReminderDataShareHelper::GetInstance() +{ + static ReminderDataShareHelper helper; + return helper; +} + +bool ReminderDataShareHelper::RegisterObserver() +{ + std::lock_guard locker(mutex_); + if (observer_ != nullptr) { + return true; + } + auto helper = CreateDataShareHelper(); + if (helper == nullptr) { + ANSR_LOGE("Create datashare helper failed."); + return false; + } + observer_ = std::make_shared(); + Uri uri(ReminderCalendarShareTable::PROXY); + helper->RegisterObserverExt(uri, observer_, false); + ReleaseDataShareHelper(helper); + return true; +} + +bool ReminderDataShareHelper::UnRegisterObserver() +{ + std::lock_guard locker(mutex_); + if (observer_ == nullptr) { + return true; + } + auto helper = CreateDataShareHelper(); + if (helper == nullptr) { + ANSR_LOGE("Create datashare helper failed."); + return false; + } + Uri uri(ReminderCalendarShareTable::PROXY); + helper->UnregisterObserverExt(uri, observer_); + ReleaseDataShareHelper(helper); + observer_ = nullptr; + return true; +} + +bool ReminderDataShareHelper::Query(std::map>& reminders) +{ + auto helper = CreateDataShareHelper(); + if (helper == nullptr) { + ANSR_LOGE("Create datashare helper failed."); + return false; + } + int64_t timestamp = GetCurrentTime(); + int64_t targetTimestamp = timestamp + DURATION_ONE_HOUR; + + std::string proxy = ReminderCalendarShareTable::PROXY; + proxy.append("?user=").append(std::to_string(curUserId_)); + Uri uri(proxy); + static std::vector columns = GetColumns(); + DataShare::DataSharePredicates predicates; + predicates.NotEqualTo(ReminderCalendarShareTable::STATE, ReminderCalendarShareTable::STATE_DISMISSED); + predicates.And(); + predicates.BeginWrap(); + predicates.BeginWrap(); + predicates.LessThanOrEqualTo(ReminderCalendarShareTable::ALARM_TIME, timestamp); + predicates.And(); + predicates.GreaterThanOrEqualTo(ReminderCalendarShareTable::END, timestamp); + predicates.EndWrap(); + predicates.Or(); + predicates.BeginWrap(); + predicates.GreaterThanOrEqualTo(ReminderCalendarShareTable::BEGIN, timestamp); + predicates.And(); + predicates.LessThanOrEqualTo(ReminderCalendarShareTable::BEGIN, targetTimestamp); + predicates.EndWrap(); + predicates.EndWrap(); + auto resultSet = helper->Query(uri, predicates, columns); + if (resultSet == nullptr) { + ReleaseDataShareHelper(helper); + return false; + } + + bool isAtLastRow = false; + int32_t ret = resultSet->IsAtLastRow(isAtLastRow); + while (ret == 0 && !isAtLastRow) { + resultSet->GoToNextRow(); + sptr reminder = CreateReminder(resultSet); + if (reminder == nullptr) { + continue; + } + reminders[reminder->GetReminderId()] = reminder; + ret = resultSet->IsAtLastRow(isAtLastRow); + } + ReleaseDataShareHelper(helper); + return true; +} + +bool ReminderDataShareHelper::Update(const int32_t reminderId, const int32_t state) +{ + auto helper = CreateDataShareHelper(); + if (helper == nullptr) { + ANSR_LOGE("Create datashare helper failed."); + return false; + } + std::string proxy = ReminderCalendarShareTable::PROXY; + proxy.append("?user=").append(std::to_string(curUserId_)); + Uri uri(proxy); + + DataShare::DataSharePredicates predicates; + predicates.EqualTo(ReminderCalendarShareTable::ID, reminderId); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(ReminderCalendarShareTable::STATE, state); + helper->UpdateEx(uri, predicates, valuesBucket); + ReleaseDataShareHelper(helper); + return true; +} + +void ReminderDataShareHelper::StartDataExtension(const int32_t reason) +{ + AAFwk::Want want; + want.SetElementName(ReminderCalendarShareTable::DATA_NAME, ReminderCalendarShareTable::ENTRY); + want.SetParam(ReminderCalendarShareTable::PARAM_CALLBACK_TYPE, reason); + IN_PROCESS_CALL_WITHOUT_RET(AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(want, nullptr)); +} + +void ReminderDataShareHelper::UpdateCalendarUid() +{ + uid_ = BundleManagerHelper::GetInstance()->GetDefaultUidByBundleName(ReminderCalendarShareTable::NAME, + curUserId_); + dataUid_ = BundleManagerHelper::GetInstance()->GetDefaultUidByBundleName(ReminderCalendarShareTable::DATA_NAME, + curUserId_); +} + +void ReminderDataShareHelper::OnDataInsert(const DataShare::DataShareObserver::ChangeInfo&) +{ + auto func = []() { + auto manager = ReminderDataManager::GetInstance(); + if (manager == nullptr) { + ANSR_LOGE("ReminderDataManager is nullptr."); + return; + } + manager->OnDataShareInsert(); + }; + int64_t timestamp = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + if (timestamp - insertTime_ > CYCLE_DATASHARE_TASK) { + insertTime_ = timestamp; + insertTask_ = false; + queue_->submit(func); + } else { + bool expected = false; + if (insertTask_.compare_exchange_strong(expected, true)) { + ffrt::task_attr taskAttr; + taskAttr.delay(DURATION_DELAY_TASK); + queue_->submit(func, taskAttr); + } + } +} + +void ReminderDataShareHelper::OnDataUpdate(const DataShare::DataShareObserver::ChangeInfo& info) +{ + std::map> reminders = CreateReminder(info); + queue_->submit([reminders = std::move(reminders)]() { + auto manager = ReminderDataManager::GetInstance(); + if (manager == nullptr) { + ANSR_LOGE("ReminderDataManager is nullptr."); + return; + } + manager->OnDataShareUpdate(reminders); + }); +} + +void ReminderDataShareHelper::OnDataDelete(const DataShare::DataShareObserver::ChangeInfo&) +{ + auto func = []() { + auto manager = ReminderDataManager::GetInstance(); + if (manager == nullptr) { + ANSR_LOGE("ReminderDataManager is nullptr."); + return; + } + manager->OnDataShareDelete(); + }; + int64_t timestamp = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + if (timestamp - deleteTime_ > CYCLE_DATASHARE_TASK) { + deleteTime_ = timestamp; + deleteTask_ = false; + queue_->submit(func); + } else { + bool expected = false; + if (deleteTask_.compare_exchange_strong(expected, true)) { + ffrt::task_attr taskAttr; + taskAttr.delay(DURATION_DELAY_TASK); + queue_->submit(func, taskAttr); + } + } +} + +std::shared_ptr ReminderDataShareHelper::CreateDataShareHelper() +{ + sptr manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (manager == nullptr) { + ANSR_LOGE("Get sa manager failed."); + return nullptr; + } + sptr remoteObj = manager->GetSystemAbility(ADVANCED_NOTIFICATION_SERVICE_ABILITY_ID); + if (remoteObj == nullptr) { + ANSR_LOGE("Get system ability failed."); + return nullptr; + } + + std::string proxy = ReminderCalendarShareTable::PROXY; + proxy.append("?user=").append(std::to_string(curUserId_)); + std::pair> ret = + DataShare::DataShareHelper::Create(remoteObj, proxy, ""); + if (ret.first == 0 && ret.second != nullptr) { + return ret.second; + } else { + ANSR_LOGE("Create DataShareHelper failed."); + return nullptr; + } +} + +bool ReminderDataShareHelper::ReleaseDataShareHelper(const std::shared_ptr& helper) +{ + if (helper == nullptr) { + ANSR_LOGE("DataShareHelper is nullptr."); + return false; + } + return helper->Release(); +} + +std::vector ReminderDataShareHelper::GetColumns() const +{ + return std::vector { + ReminderCalendarShareTable::ID, ReminderCalendarShareTable::EVENT_ID, + ReminderCalendarShareTable::BEGIN, ReminderCalendarShareTable::END, + ReminderCalendarShareTable::ALARM_TIME, ReminderCalendarShareTable::STATE, + ReminderCalendarShareTable::MINUTES, ReminderCalendarShareTable::TITLE, + ReminderCalendarShareTable::CONTENT, ReminderCalendarShareTable::WANT_AGENT, + ReminderCalendarShareTable::BUTTONS, ReminderCalendarShareTable::SLOT_TYPE + }; +} + +sptr ReminderDataShareHelper::CreateReminder( + const std::shared_ptr& result) +{ + sptr reminder = sptr::MakeSptr(); + InitBaseInfo(reminder); + uint64_t triggerTime = 0; + GetRdbValue(result, ReminderCalendarShareTable::ALARM_TIME, triggerTime); + reminder->SetTriggerTimeInMilli(triggerTime); + + int32_t reminderId = 0; + GetRdbValue(result, ReminderCalendarShareTable::ID, reminderId); + reminder->SetReminderId(reminderId); + int32_t notificationId = 0; + GetRdbValue(result, ReminderCalendarShareTable::EVENT_ID, notificationId); + reminder->SetNotificationId(notificationId); + + int32_t slotType = 0; + GetRdbValue(result, ReminderCalendarShareTable::SLOT_TYPE, slotType); + reminder->SetSlotType(NotificationConstant::SlotType(slotType)); + + std::string title; + GetRdbValue(result, ReminderCalendarShareTable::TITLE, title); + reminder->SetTitle(title); + std::string content; + GetRdbValue(result, ReminderCalendarShareTable::CONTENT, content); + reminder->SetContent(content); + std::string actionButtons; + GetRdbValue(result, ReminderCalendarShareTable::BUTTONS, actionButtons); + reminder->DeserializeButtonInfoFromJson(actionButtons); + std::string wantAgent; + GetRdbValue(result, ReminderCalendarShareTable::WANT_AGENT, wantAgent); + reminder->DeserializeWantAgent(wantAgent, 0); + uint64_t minutes = 0; + GetRdbValue(result, ReminderCalendarShareTable::MINUTES, minutes); + minutes = minutes * 60 * 1000; + uint64_t endDateTime = 0; + GetRdbValue(result, ReminderCalendarShareTable::END, endDateTime); + reminder->SetAutoDeletedTime(endDateTime); + + ReminderRequestCalendar* calendar = static_cast(reminder.GetRefPtr()); + uint64_t dateTime = 0; + GetRdbValue(result, ReminderCalendarShareTable::BEGIN, dateTime); + dateTime -= minutes; + calendar->SetDateTime(dateTime); + calendar->SetEndDateTime(endDateTime); + + time_t now = static_cast(dateTime/1000); + struct tm nowTime; + (void)localtime_r(&now, &nowTime); + calendar->SetFirstDesignateYear(static_cast(ReminderRequest::GetActualTime( + ReminderRequest::TimeTransferType::YEAR, nowTime.tm_year))); + calendar->SetFirstDesignageMonth(static_cast(ReminderRequest::GetActualTime( + ReminderRequest::TimeTransferType::MONTH, nowTime.tm_mon))); + calendar->SetFirstDesignateDay(nowTime.tm_mday); + return reminder; +} + +std::map> ReminderDataShareHelper::CreateReminder( + const DataShare::DataShareObserver::ChangeInfo& info) +{ + std::map> reminders; + for (auto& values : info.valueBuckets_) { + sptr reminder = sptr::MakeSptr(); + InitBaseInfo(reminder); + auto iter = values.find(ReminderCalendarShareTable::ALARM_TIME); + if (iter != values.end()) { + reminder->SetTriggerTimeInMilli(static_cast(std::get(iter->second))); + } + } +} + +void ReminderDataShareHelper::InitBaseInfo(sptr& reminder) +{ + reminder->SetRingDuration(0); + reminder->InitUserId(curUserId_); + reminder->InitUid(uid_); + reminder->InitCreatorUid(dataUid_); + reminder->SetShare(true); + reminder->InitBundleName(ReminderCalendarShareTable::NAME); + reminder->InitCreatorBundleName(ReminderCalendarShareTable::DATA_NAME); + reminder->SetSystemApp(true); + reminder->SetTapDismissed(true); +} + +ReminderDataShareHelper::ReminderDataShareHelper() +{ + queue_ = std::make_shared("ReminderDataShareHelper"); + insertTime_ = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + deleteTime_.store(insertTime_.load()); +} + +void ReminderDataShareHelper::ReminderDataObserver::OnChange(const ChangeInfo& info) +{ + switch (info.changeType_) { + case DataShare::DataShareObserver::ChangeType::INSERT: { + ReminderDataShareHelper::GetInstance().OnDataInsert(info); + break; + } + case DataShare::DataShareObserver::ChangeType::UPDATE: { + ReminderDataShareHelper::GetInstance().OnDataUpdate(info); + break; + } + case DataShare::DataShareObserver::ChangeType::DELETE: { + ReminderDataShareHelper::GetInstance().OnDataDelete(info); + break; + } + default: { + break; + } + } +} +} \ No newline at end of file diff --git a/services/reminder/src/reminder_event_manager.cpp b/services/reminder/src/reminder_event_manager.cpp index c26ed1d98..f633ab733 100644 --- a/services/reminder/src/reminder_event_manager.cpp +++ b/services/reminder/src/reminder_event_manager.cpp @@ -175,7 +175,7 @@ void ReminderEventManager::ReminderEventCustomSubscriber::OnReceiveEvent(const E return; } if (action == ReminderRequest::REMINDER_EVENT_LOAD_REMINDER) { - reminderDataManager_->ReceiveLoadReminderEvent(); + reminderDataManager_->OnLoadReminderEvent(want); return; } } diff --git a/services/reminder/src/reminder_store.cpp b/services/reminder/src/reminder_store.cpp index 4a75c5862..9ab828521 100644 --- a/services/reminder/src/reminder_store.cpp +++ b/services/reminder/src/reminder_store.cpp @@ -382,6 +382,9 @@ int32_t ReminderStore::UpdateOrInsert( ANSR_LOGE("Rdb store is not initialized."); return STATE_FAIL; } + if (reminder != nullptr && reminder->IsShare()) { + return STATE_OK; + } if (IsReminderExist(reminder)) { return Update(reminder); } else { -- Gitee