diff --git a/frameworks/ans/core/BUILD.gn b/frameworks/ans/core/BUILD.gn index 8bd4d57f7fc362b94d278c8fbb52aa07579b26eb..cc8e50066cefdb0a65e26b6ec60f8bf7df113faf 100644 --- a/frameworks/ans/core/BUILD.gn +++ b/frameworks/ans/core/BUILD.gn @@ -74,6 +74,7 @@ ohos_shared_library("ans_core") { "${frameworks_path}/ans/native/src/reminder_helper.cpp", "${frameworks_path}/ans/native/src/reminder_request.cpp", "${frameworks_path}/ans/native/src/reminder_request_alarm.cpp", + "${frameworks_path}/ans/native/src/reminder_request_calendar.cpp", "${frameworks_path}/ans/native/src/reminder_request_timer.cpp", ] diff --git a/frameworks/ans/core/src/ans_manager_proxy.cpp b/frameworks/ans/core/src/ans_manager_proxy.cpp index b0ab15db8b03e6b824f911e586ac25ffd9809e13..ce1d52cebc82ce0e0c3c0decacac5488fecb0529 100644 --- a/frameworks/ans/core/src/ans_manager_proxy.cpp +++ b/frameworks/ans/core/src/ans_manager_proxy.cpp @@ -21,6 +21,7 @@ #include "message_parcel.h" #include "parcel.h" #include "reminder_request_alarm.h" +#include "reminder_request_calendar.h" #include "reminder_request_timer.h" namespace OHOS { @@ -2271,6 +2272,9 @@ ErrCode AnsManagerProxy::ReadReminders( } else if (ReminderRequest::ReminderType::TIMER == reminderType) { ANSR_LOGD("[GetValidReminders] timer"); reminder = reply.ReadParcelable(); + } else if (ReminderRequest::ReminderType::CALENDAR == reminderType) { + ANSR_LOGD("[GetValidReminders] calendar"); + reminder = reply.ReadParcelable(); } else { ANSR_LOGW("[GetValidReminders] type=%{public}d", typeInfo); return ERR_ANS_INVALID_PARAM; diff --git a/frameworks/ans/core/src/ans_manager_stub.cpp b/frameworks/ans/core/src/ans_manager_stub.cpp index 9dee804e9e9b9d43fdac876fd61e91fd106b9f35..979f0b2edf15d253cdaa1d1c23ced0255a5bddb6 100644 --- a/frameworks/ans/core/src/ans_manager_stub.cpp +++ b/frameworks/ans/core/src/ans_manager_stub.cpp @@ -21,6 +21,7 @@ #include "message_parcel.h" #include "parcel.h" #include "reminder_request_alarm.h" +#include "reminder_request_calendar.h" #include "reminder_request_timer.h" namespace OHOS { @@ -1417,6 +1418,9 @@ ErrCode AnsManagerStub::HandlePublishReminder(MessageParcel &data, MessageParcel } else if (ReminderRequest::ReminderType::TIMER == reminderType) { ANSR_LOGD("Publish timer"); reminder = data.ReadParcelable(); + } else if (ReminderRequest::ReminderType::CALENDAR == reminderType) { + ANSR_LOGD("Publish calendar"); + reminder = data.ReadParcelable(); } else { ANSR_LOGE("Reminder type invalid"); return ERR_ANS_INVALID_PARAM; diff --git a/frameworks/ans/core/src/ans_notification.cpp b/frameworks/ans/core/src/ans_notification.cpp index a9249491d82d90cc3ffb95a25795158fed937284..6c4873d6cccdb784b7cd4e1abfbd824f73152d2b 100644 --- a/frameworks/ans/core/src/ans_notification.cpp +++ b/frameworks/ans/core/src/ans_notification.cpp @@ -19,6 +19,7 @@ #include "ans_log_wrapper.h" #include "iservice_registry.h" #include "reminder_request_alarm.h" +#include "reminder_request_calendar.h" #include "reminder_request_timer.h" #include "system_ability_definition.h" @@ -964,19 +965,30 @@ ErrCode AnsNotification::PublishReminder(ReminderRequest &reminder) ANS_LOGE("GetAnsManagerProxy fail."); return ERR_ANS_SERVICE_NOT_CONNECTED; } - sptr tarReminder; - if (reminder.GetReminderType() == ReminderRequest::ReminderType::ALARM) { - ANSR_LOGI("Publish alarm"); - ReminderRequestAlarm &alarm = (ReminderRequestAlarm &)reminder; - tarReminder = new (std::nothrow) ReminderRequestAlarm(alarm); - } else if (reminder.GetReminderType() == ReminderRequest::ReminderType::TIMER) { - ANSR_LOGI("Publish timer"); - ReminderRequestTimer &timer = (ReminderRequestTimer &)reminder; - tarReminder = new (std::nothrow) ReminderRequestTimer(timer); - } else { - ANSR_LOGW("PublishReminder fail."); - return ERR_ANS_INVALID_PARAM; + switch (reminder.GetReminderType()) { + case (ReminderRequest::ReminderType::TIMER): { + ANSR_LOGI("Publish timer"); + ReminderRequestTimer &timer = (ReminderRequestTimer &)reminder; + tarReminder = new (std::nothrow) ReminderRequestTimer(timer); + break; + } + case (ReminderRequest::ReminderType::ALARM): { + ANSR_LOGI("Publish alarm"); + ReminderRequestAlarm &alarm = (ReminderRequestAlarm &)reminder; + tarReminder = new (std::nothrow) ReminderRequestAlarm(alarm); + break; + } + case (ReminderRequest::ReminderType::CALENDAR): { + ANSR_LOGI("Publish calendar"); + ReminderRequestCalendar &calendar = (ReminderRequestCalendar &)reminder; + tarReminder = new (std::nothrow) ReminderRequestCalendar(calendar); + break; + } + default: { + ANSR_LOGW("PublishReminder fail."); + return ERR_ANS_INVALID_PARAM; + } } ErrCode code = ansManagerProxy_->PublishReminder(tarReminder); reminder.SetReminderId(tarReminder->GetReminderId()); diff --git a/frameworks/ans/native/src/reminder_helper.cpp b/frameworks/ans/native/src/reminder_helper.cpp index 39fe3105db9e4289f0e28c590c0e1fc8497bd39b..3197916aec4e4f7c1608785cb4759518bdf28f8e 100644 --- a/frameworks/ans/native/src/reminder_helper.cpp +++ b/frameworks/ans/native/src/reminder_helper.cpp @@ -29,6 +29,7 @@ namespace Notification { ErrCode ReminderHelper::PublishReminder(ReminderRequest &reminder) { ANSR_LOGI("PublishReminder start"); + NotificationSlot slot(reminder.GetSlotType()); NotificationHelper::AddNotificationSlot(slot); return DelayedSingleton::GetInstance()->PublishReminder(reminder); diff --git a/frameworks/ans/native/src/reminder_request.cpp b/frameworks/ans/native/src/reminder_request.cpp index 1f7f16d4e5274500e12e4b0d387e1430d21bb42e..bb8245dfb3d24d88d57d30150778bdb164d9dc49 100644 --- a/frameworks/ans/native/src/reminder_request.cpp +++ b/frameworks/ans/native/src/reminder_request.cpp @@ -21,11 +21,17 @@ namespace OHOS { namespace Notification { int32_t ReminderRequest::GLOBAL_ID = 0; -const uint64_t ReminderRequest::INVALID_LONG_VALUE = 0; +const uint64_t ReminderRequest::INVALID_LONG_LONG_VALUE = 0; +const uint16_t ReminderRequest::INVALID_U16_VALUE = 0; const uint16_t ReminderRequest::MILLI_SECONDS = 1000; const uint16_t ReminderRequest::SAME_TIME_DISTINGUISH_MILLISECONDS = 1000; +const uint32_t ReminderRequest::MIN_TIME_INTERVAL_IN_MILLI = 5 * 60 * 1000; +const uint8_t ReminderRequest::INVALID_U8_VALUE = 0; const uint8_t ReminderRequest::REMINDER_STATUS_INACTIVE = 0; +const uint8_t ReminderRequest::REMINDER_STATUS_ACTIVE = 1; +const uint8_t ReminderRequest::REMINDER_STATUS_ALERTING = 2; const uint8_t ReminderRequest::REMINDER_STATUS_SHOWING = 4; +const uint8_t ReminderRequest::REMINDER_STATUS_SNOOZE = 8; const std::string ReminderRequest::NOTIFICATION_LABEL = "REMINDER_AGENT"; const std::string ReminderRequest::REMINDER_EVENT_ALARM_ALERT = "ohos.event.notification.reminder.ALARM_ALERT"; const std::string ReminderRequest::REMINDER_EVENT_CLOSE_ALERT = "ohos.event.notification.reminder.CLOSE_ALERT"; @@ -34,40 +40,71 @@ const std::string ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT = "ohos.event.no const std::string ReminderRequest::REMINDER_EVENT_REMOVE_NOTIFICATION = "ohos.event.notification.reminder.REMOVE_NOTIFICATION"; const std::string ReminderRequest::PARAM_REMINDER_ID = "REMINDER_ID"; +const int ReminderRequest::BASE_YEAR = 1900; ReminderRequest::ReminderRequest() { wantAgentInfo_ = wantAgentInfo_ == nullptr ? std::make_shared() : wantAgentInfo_; + maxScreenWantAgentInfo_ = + maxScreenWantAgentInfo_ == nullptr ? std::make_shared() : maxScreenWantAgentInfo_; } ReminderRequest::ReminderRequest(const ReminderRequest &other) { - this->actionButtonMap_ = other.actionButtonMap_; this->content_ = other.content_; this->expiredContent_ = other.expiredContent_; + this->snoozeContent_ = other.snoozeContent_; + this->displayContent_ = other.displayContent_; + this->title_ = other.title_; + this->isExpired_ = other.isExpired_; + this->snoozeTimes_ = other.snoozeTimes_; + this->snoozeTimesDynamic_ = other.snoozeTimesDynamic_; + this->state_ = other.state_; this->notificationId_ = other.notificationId_; this->reminderId_ = other.reminderId_; + this->reminderTimeInMilli_ = other.reminderTimeInMilli_; + this->ringDurationInMilli_ = other.ringDurationInMilli_; + this->triggerTimeInMilli_ = other.triggerTimeInMilli_; + this->timeIntervalInMilli_ = other.timeIntervalInMilli_; this->reminderType_ = other.reminderType_; this->slotType_ = other.slotType_; - this->title_ = other.title_; - this->triggerTimeInMilli_ = other.triggerTimeInMilli_; + this->notificationRequest_ = other.notificationRequest_; this->wantAgentInfo_ = other.wantAgentInfo_; + this->maxScreenWantAgentInfo_ = other.maxScreenWantAgentInfo_; + this->actionButtonMap_ = other.actionButtonMap_; } ReminderRequest::ReminderRequest(ReminderType reminderType) { reminderType_ = reminderType; wantAgentInfo_ = wantAgentInfo_ == nullptr ? std::make_shared() : wantAgentInfo_; + maxScreenWantAgentInfo_ = + maxScreenWantAgentInfo_ == nullptr ? std::make_shared() : maxScreenWantAgentInfo_; } bool ReminderRequest::CanRemove() { - if ((state_ & REMINDER_STATUS_SHOWING) == 0) { + if ((state_ & (REMINDER_STATUS_SHOWING | REMINDER_STATUS_ALERTING | REMINDER_STATUS_ACTIVE)) == 0) { return true; } return false; } +bool ReminderRequest::CanShow() const +{ + // when system time change by user manually, and the reminde is to show immediately, + // the show reminder just need to be triggered by ReminderDataManager#RefreshRemindersLocked(uint8_t). + // we need to make the REMINDER_EVENT_ALARM_ALERT do nothing. + uint64_t nowInstantMilli = GetNowInstantMilli(); + if (nowInstantMilli == 0) { + return false; + } + if ((nowInstantMilli - GetReminderTimeInMilli()) < MIN_TIME_INTERVAL_IN_MILLI) { + return false; + } + return true; +} + std::string ReminderRequest::Dump() const { struct tm *timeInfo; @@ -77,7 +114,7 @@ std::string ReminderRequest::Dump() const char dateTimeBuffer[dateTimeLen]; (void)strftime(dateTimeBuffer, dateTimeLen, "%Y-%m-%d %H:%M:%S", timeInfo); return "Reminder[" - "id=" + std::to_string(reminderId_) + + "reminderId=" + std::to_string(reminderId_) + ", type=" + std::to_string(static_cast(reminderType_)) + ", state=" + GetState(state_) + ", nextTriggerTime=" + dateTimeBuffer + @@ -86,8 +123,9 @@ std::string ReminderRequest::Dump() const ReminderRequest& ReminderRequest::SetActionButton(const std::string &title, const ActionButtonType &type) { - if (type != ActionButtonType::CLOSE) { - ANSR_LOGI("Button type only support: %{public}d", static_cast(ActionButtonType::CLOSE)); + if (type != ActionButtonType::CLOSE && type != ActionButtonType::SNOOZE) { + ANSR_LOGI("Button type only support: %{public}d or %{public}d", + static_cast(ActionButtonType::CLOSE), static_cast(ActionButtonType::SNOOZE)); return *this; } ActionButtonInfo actionButtonInfo; @@ -144,20 +182,24 @@ void ReminderRequest::OnClose(bool updateNext) ANSR_LOGE("onClose, the state of reminder is incorrect, state:%{public}s", GetState(state_).c_str()); return; } - SetState(false, REMINDER_STATUS_SHOWING, "onClose()"); + SetState(false, REMINDER_STATUS_SHOWING | REMINDER_STATUS_SNOOZE, "onClose()"); + if ((state_ & REMINDER_STATUS_ALERTING) != 0) { + SetState(false, REMINDER_STATUS_ALERTING, "onClose"); + } if (updateNext) { - uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(false); - if (nextTriggerTime == INVALID_LONG_VALUE) { + uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(true, false); + if (nextTriggerTime == INVALID_LONG_LONG_VALUE) { isExpired_ = true; } else { SetTriggerTimeInMilli(nextTriggerTime); + snoozeTimesDynamic_ = snoozeTimes_; } } } bool ReminderRequest::OnDateTimeChange() { - uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(false); + uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(true, false); return HandleSysTimeChange(triggerTimeInMilli_, nextTriggerTime); } @@ -167,19 +209,19 @@ bool ReminderRequest::HandleSysTimeChange(uint64_t oriTriggerTime, uint64_t optT return false; } bool showImmediately = false; - if (optTriggerTime != INVALID_LONG_VALUE && optTriggerTime <= oriTriggerTime) { + if (optTriggerTime != INVALID_LONG_LONG_VALUE && optTriggerTime <= oriTriggerTime) { // case1. switch to a previous time SetTriggerTimeInMilli(optTriggerTime); + snoozeTimesDynamic_ = snoozeTimes_; } else { - time_t now; - time(&now); // unit is seconds. - if (static_cast(now) < 0) { - ANSR_LOGE("Get now time error"); + uint64_t now = GetNowInstantMilli(); + if (now == 0) { return false; } - if (oriTriggerTime <= (static_cast(now) * MILLI_SECONDS)) { + if (oriTriggerTime <= now) { // case2. switch to a future time, trigger time is less than now time. // when the reminder show immediately, trigger time will update in onShow function. + snoozeTimesDynamic_ = 0; showImmediately = true; } else { // case3. switch to a future time, trigger time is larger than now time. @@ -189,19 +231,23 @@ bool ReminderRequest::HandleSysTimeChange(uint64_t oriTriggerTime, uint64_t optT return showImmediately; } -bool ReminderRequest::HandleTimeZoneChange( - uint64_t oldZoneTriggerTime, uint64_t newZoneTriggerTime, uint64_t optTriggerTime) +bool ReminderRequest::HandleTimeZoneChange(uint64_t oldZoneTriggerTime, uint64_t newZoneTriggerTime, uint64_t optTriggerTime) { if (isExpired_) { return false; } ANSR_LOGD("Handle timezone change, oldZoneTriggerTime:%{public}llu, newZoneTriggerTime:%{public}llu", (unsigned long long)oldZoneTriggerTime, (unsigned long long)newZoneTriggerTime); + if (oldZoneTriggerTime == newZoneTriggerTime) { + return false; + } bool showImmediately = false; - if (optTriggerTime != INVALID_LONG_VALUE && oldZoneTriggerTime < newZoneTriggerTime) { + if (optTriggerTime != INVALID_LONG_LONG_VALUE && oldZoneTriggerTime < newZoneTriggerTime) { // case1. timezone change to smaller SetTriggerTimeInMilli(optTriggerTime); + snoozeTimesDynamic_ = snoozeTimes_; } else { + // case2. timezone change to larger time_t now; time(&now); // unit is seconds. if (static_cast(now) < 0) { @@ -209,10 +255,10 @@ bool ReminderRequest::HandleTimeZoneChange( return false; } if (newZoneTriggerTime <= (static_cast(now))) { - // case2. timezone change to larger + snoozeTimesDynamic_ = 0; showImmediately = true; } else { - SetTriggerTimeInMilli(newZoneTriggerTime); + SetTriggerTimeInMilli(newZoneTriggerTime * MILLI_SECONDS); showImmediately = false; } } @@ -221,15 +267,91 @@ bool ReminderRequest::HandleTimeZoneChange( void ReminderRequest::OnSameNotificationIdCovered() { - SetState(false, REMINDER_STATUS_SHOWING, "OnSameNotificationIdCovered"); + SetState(false, REMINDER_STATUS_ALERTING | REMINDER_STATUS_SHOWING | REMINDER_STATUS_SNOOZE, + "OnSameNotificationIdCovered"); } -void ReminderRequest::OnShow(bool isSysTimeChanged, bool allowToNotify) +void ReminderRequest::OnShow(bool isPlaySoundOrVibration, bool isSysTimeChanged, bool allowToNotify) { + if ((state_ & (REMINDER_STATUS_ACTIVE | REMINDER_STATUS_SNOOZE)) != 0) { + SetState(false, REMINDER_STATUS_ACTIVE | REMINDER_STATUS_SNOOZE, "onShow()"); + } + if (isSysTimeChanged) { + uint64_t nowInstantMilli = GetNowInstantMilli(); + if (nowInstantMilli == 0) { + ANSR_LOGW("Onshow, get now time error"); + } + reminderTimeInMilli_ = nowInstantMilli; + } else { + reminderTimeInMilli_ = triggerTimeInMilli_; + } + UpdateNextReminder(false); if (allowToNotify) { SetState(true, REMINDER_STATUS_SHOWING, "OnShow"); + if (isPlaySoundOrVibration) { + SetState(true, REMINDER_STATUS_ALERTING, "OnShow"); + } + UpdateNotificationStateForAlert(); } - UpdateNextReminder(); +} + +void ReminderRequest::OnShowFail() +{ + SetState(false, REMINDER_STATUS_SHOWING, "OnShowFailed()"); +} + +bool ReminderRequest::OnSnooze() +{ + if ((state_ & REMINDER_STATUS_SNOOZE) != 0) { + ANSR_LOGW("onSnooze, the state of reminder is incorrect, state: %{public}s", (GetState(state_)).c_str()); + return false; + } + if ((state_ & REMINDER_STATUS_ALERTING) != 0) { + SetState(false, REMINDER_STATUS_ALERTING, "onSnooze()"); + } + if (!UpdateNextReminder(true)) { + return false; + } + UpdateNotificationStateForSnooze(); + if (timeIntervalInMilli_ > 0) { + SetState(true, REMINDER_STATUS_SNOOZE, "onSnooze()"); + } + return true; +} + +void ReminderRequest::OnStart() +{ + if ((state_ & REMINDER_STATUS_ACTIVE) != 0) { + ANSR_LOGE( + "start failed, the state of reminder is incorrect, state: %{public}s", (GetState(state_)).c_str()); + return; + } + if (isExpired_) { + ANSR_LOGE("start failed, the reminder is expired"); + return; + } + SetState(true, REMINDER_STATUS_ACTIVE, "OnStart()"); +} + +void ReminderRequest::OnStop() +{ + ANSR_LOGI("Stop the previous active reminder, %{public}s", this->Dump().c_str()); + if ((state_ & REMINDER_STATUS_ACTIVE) == 0) { + ANSR_LOGW("onStop, the state of reminder is incorrect, state: %{public}s", (GetState(state_)).c_str()); + return; + } + SetState(false, REMINDER_STATUS_ACTIVE, "OnStop"); +} + +bool ReminderRequest::OnTerminate() +{ + if ((state_ & REMINDER_STATUS_ALERTING) == 0) { + ANSR_LOGW("onTerminate, the state of reminder is %{public}s", (GetState(state_)).c_str()); + return false; + } + SetState(false, REMINDER_STATUS_ALERTING, "onTerminate"); + UpdateNotificationStateForAlert(); + return true; } bool ReminderRequest::OnTimeZoneChange() @@ -237,10 +359,17 @@ bool ReminderRequest::OnTimeZoneChange() time_t oldZoneTriggerTime = static_cast(triggerTimeInMilli_ / MILLI_SECONDS); struct tm *oriTime = gmtime(&oldZoneTriggerTime); time_t newZoneTriggerTime = mktime(oriTime); - uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(false); + uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(true, false); return HandleTimeZoneChange(oldZoneTriggerTime, newZoneTriggerTime, nextTriggerTime); } +ReminderRequest& ReminderRequest::SetMaxScreenWantAgentInfo( + const std::shared_ptr &maxScreenWantAgentInfo) +{ + maxScreenWantAgentInfo_ = maxScreenWantAgentInfo; + return *this; +} + ReminderRequest& ReminderRequest::SetNotificationId(int32_t notificationId) { notificationId_ = notificationId; @@ -253,6 +382,44 @@ ReminderRequest& ReminderRequest::SetSlotType(const NotificationConstant::SlotTy return *this; } +ReminderRequest& ReminderRequest::SetSnoozeContent(const std::string &snoozeContent) +{ + snoozeContent_ = snoozeContent; + return *this; +} + +ReminderRequest& ReminderRequest::SetSnoozeTimes(const uint8_t snoozeTimes) +{ + snoozeTimes_ = snoozeTimes; + SetSnoozeTimesDynamic(snoozeTimes); + return *this; +} + +ReminderRequest& ReminderRequest::SetSnoozeTimesDynamic(const uint8_t snooziTimes) +{ + snoozeTimesDynamic_ = snooziTimes; + return *this; +} + +ReminderRequest& ReminderRequest::SetTimeInterval(const uint64_t timeIntervalInSeconds) +{ + if (timeIntervalInSeconds < 0 || timeIntervalInSeconds > (UINT64_MAX / MILLI_SECONDS)) { + ANSR_LOGW("SetTimeInterval, replace to set (0s), for the given is out of legal range"); + timeIntervalInMilli_ = 0; + } else { + uint64_t timeIntervalInMilli = timeIntervalInSeconds * MILLI_SECONDS; + if (timeIntervalInMilli > 0 && timeIntervalInMilli < MIN_TIME_INTERVAL_IN_MILLI) { + ANSR_LOGW("SetTimeInterval, replace to set %{public}u, for the given is 0<%{public}llu<%{public}u", + MIN_TIME_INTERVAL_IN_MILLI / MILLI_SECONDS, (unsigned long long)timeIntervalInSeconds, + MIN_TIME_INTERVAL_IN_MILLI / MILLI_SECONDS); + timeIntervalInMilli_ = MIN_TIME_INTERVAL_IN_MILLI; + } else { + timeIntervalInMilli_ = timeIntervalInMilli; + } + } + return *this; +} + ReminderRequest& ReminderRequest::SetTitle(const std::string &title) { title_ = title; @@ -270,8 +437,20 @@ ReminderRequest& ReminderRequest::SetWantAgentInfo(const std::shared_ptr ReminderRequest::GetActionButtons() - const +bool ReminderRequest::ShouldShowImmediately() const +{ + uint64_t nowInstantMilli = GetNowInstantMilli(); + if (nowInstantMilli == 0) { + return false; + } + if (triggerTimeInMilli_ > nowInstantMilli) { + return false; + } + return true; +} + +std::map ReminderRequest::GetActionButtons() const { return actionButtonMap_; } @@ -286,6 +465,11 @@ std::string ReminderRequest::GetExpiredContent() const return expiredContent_; } +std::shared_ptr ReminderRequest::GetMaxScreenWantAgentInfo() const +{ + return maxScreenWantAgentInfo_; +} + int32_t ReminderRequest::GetNotificationId() const { return notificationId_; @@ -301,21 +485,62 @@ int32_t ReminderRequest::GetReminderId() const return reminderId_; } +uint64_t ReminderRequest::GetReminderTimeInMilli() const +{ + return reminderTimeInMilli_; +} + void ReminderRequest::SetReminderId(int32_t reminderId) { reminderId_ = reminderId; } +void ReminderRequest::SetReminderTimeInMilli(const uint64_t reminderTimeInMilli) +{ + reminderTimeInMilli_ = reminderTimeInMilli; +} + +ReminderRequest& ReminderRequest::SetRingDuration(const uint64_t ringDurationInSeconds) +{ + if (ringDurationInSeconds <= 0 || ringDurationInSeconds > (UINT64_MAX / MILLI_SECONDS)) { + ANSR_LOGW("setRingDuration, replace to set (1s), for the given is out of legal range"); + ringDurationInMilli_ = MILLI_SECONDS; + } else { + ringDurationInMilli_ = ringDurationInSeconds * MILLI_SECONDS; + } + return *this; +} + NotificationConstant::SlotType ReminderRequest::GetSlotType() const { return slotType_; } +std::string ReminderRequest::GetSnoozeContent() const +{ + return snoozeContent_; +} + +uint8_t ReminderRequest::GetSnoozeTimes() const +{ + return snoozeTimes_; +} + +uint8_t ReminderRequest::GetSnoozeTimesDynamic() const +{ + return snoozeTimesDynamic_; +} + uint8_t ReminderRequest::GetState() const { return state_; } +uint64_t ReminderRequest::GetTimeInterval() const +{ + return timeIntervalInMilli_ / MILLI_SECONDS; +} + std::string ReminderRequest::GetTitle() const { return title_; @@ -336,6 +561,11 @@ ReminderRequest::ReminderType ReminderRequest::GetReminderType() const return reminderType_; } +uint16_t ReminderRequest::GetRingDuration() const +{ + return ringDurationInMilli_ / MILLI_SECONDS; +} + bool ReminderRequest::UpdateNextReminder() { return false; @@ -343,20 +573,30 @@ bool ReminderRequest::UpdateNextReminder() void ReminderRequest::UpdateNotificationRequest(UpdateNotificationType type, std::string extra) { - ANSR_LOGI("UpdateNotification type=%{public}d", static_cast(type)); - switch (type) { + switch(type) { case UpdateNotificationType::COMMON: { + ANSR_LOGI("UpdateNotification common information"); UpdateNotificationCommon(); break; } - case UpdateNotificationType::ACTION_BUTTON: { - AddActionButtons(); - break; - } case UpdateNotificationType::REMOVAL_WANT_AGENT: { + ANSR_LOGI("UpdateNotification removal_want_agent"); AddRemovalWantAgent(); break; } + case UpdateNotificationType::WANT_AGENT: { + ANSR_LOGI("UpdateNotification want_agent"); + AppExecFwk::ElementName wantAgent("", wantAgentInfo_->pkgName, wantAgentInfo_->abilityName); + SetWantAgent(wantAgent); + break; + } + case UpdateNotificationType::MAX_SCREEN_WANT_AGENT: { + ANSR_LOGI("UpdateNotification max_screen_want_agent"); + AppExecFwk::ElementName maxScreenWantAgent( + "", maxScreenWantAgentInfo_->pkgName, maxScreenWantAgentInfo_->abilityName); + SetMaxScreenWantAgent(maxScreenWantAgent); + break; + } case UpdateNotificationType::CONTENT: { break; } @@ -376,6 +616,10 @@ bool ReminderRequest::Marshalling(Parcel &parcel) const ANSR_LOGE("Failed to write expiredContent"); return false; } + if (!parcel.WriteString(snoozeContent_)) { + ANSR_LOGE("Failed to write snoozeContent"); + return false; + } if (!parcel.WriteString(title_)) { ANSR_LOGE("Failed to write title"); return false; @@ -388,6 +632,20 @@ bool ReminderRequest::Marshalling(Parcel &parcel) const ANSR_LOGE("Failed to write wantAgentInfo`s pkgName"); return false; } + if (!parcel.WriteString(maxScreenWantAgentInfo_->abilityName)) { + ANSR_LOGE("Failed to write maxScreenWantAgentInfo`s abilityName"); + return false; + } + if (!parcel.WriteString(maxScreenWantAgentInfo_->pkgName)) { + ANSR_LOGE("Failed to write maxScreenWantAgentInfo`s pkgName"); + return false; + } + + // write bool + if (!parcel.WriteBool(isExpired_)) { + ANSR_LOGE("Failed to write isExpired"); + return false; + } // write int if (!parcel.WriteInt32(reminderId_)) { @@ -402,6 +660,30 @@ bool ReminderRequest::Marshalling(Parcel &parcel) const ANSR_LOGE("Failed to write triggerTimeInMilli"); return false; } + if (!parcel.WriteUint64(timeIntervalInMilli_)) { + ANSR_LOGE("Failed to write timeIntervalInMilli"); + return false; + } + if (!parcel.WriteUint64(ringDurationInMilli_)) { + ANSR_LOGE("Failed to write ringDurationInMilli"); + return false; + } + if (!parcel.WriteUint64(reminderTimeInMilli_)) { + ANSR_LOGE("Failed to write reminderTimeInMilli"); + return false; + } + if (!parcel.WriteUint8(snoozeTimes_)) { + ANSR_LOGE("Failed to write snoozeTimes"); + return false; + } + if (!parcel.WriteUint8(snoozeTimesDynamic_)) { + ANSR_LOGE("Failed to write snoozeTimesDynamic"); + return false; + } + if (!parcel.WriteUint8(state_)) { + ANSR_LOGE("Failed to write state"); + return false; + } // write enum if (!parcel.WriteUint8(static_cast(reminderType_))) { @@ -454,6 +736,10 @@ bool ReminderRequest::ReadFromParcel(Parcel &parcel) ANSR_LOGE("to read expiredContent"); return false; } + if (!parcel.ReadString(snoozeContent_)) { + ANSR_LOGE("to read snoozeContent"); + return false; + } if (!parcel.ReadString(title_)) { ANSR_LOGE("Failed to read title"); return false; @@ -466,6 +752,20 @@ bool ReminderRequest::ReadFromParcel(Parcel &parcel) ANSR_LOGE("Failed to read wantAgentInfo`s pkgName"); return false; } + if (!parcel.ReadString(maxScreenWantAgentInfo_->abilityName)) { + ANSR_LOGE("Failed to read maxScreenWantAgentInfo`s abilityName"); + return false; + } + if (!parcel.ReadString(maxScreenWantAgentInfo_->pkgName)) { + ANSR_LOGE("Failed to read maxScreenWantAgentInfo`s pkgName"); + return false; + } + + // read bool + if (!parcel.ReadBool(isExpired_)) { + ANSR_LOGE("Failed to read isExpired"); + return false; + } // read int int32_t tempReminderId = -1; @@ -483,6 +783,30 @@ bool ReminderRequest::ReadFromParcel(Parcel &parcel) ANSR_LOGE("Failed to read triggerTimeInMilli"); return false; } + if (!parcel.ReadUint64(timeIntervalInMilli_)) { + ANSR_LOGE("Failed to read timeIntervalInMilli"); + return false; + } + if (!parcel.ReadUint64(ringDurationInMilli_)) { + ANSR_LOGE("Failed to read ringDurationInMilli"); + return false; + } + if (!parcel.ReadUint64(reminderTimeInMilli_)) { + ANSR_LOGE("Failed to read reminderTimeInMilli"); + return false; + } + if (!parcel.ReadUint8(snoozeTimes_)) { + ANSR_LOGE("Failed to read snoozeTimes"); + return false; + } + if (!parcel.ReadUint8(snoozeTimesDynamic_)) { + ANSR_LOGE("Failed to read snoozeTimesDynamic"); + return false; + } + if (!parcel.ReadUint8(state_)) { + ANSR_LOGE("Failed to read state"); + return false; + } // read enum uint8_t reminderType = static_cast(ReminderType::INVALID); @@ -525,32 +849,91 @@ bool ReminderRequest::ReadFromParcel(Parcel &parcel) void ReminderRequest::InitNotificationRequest() { ANSR_LOGI("Init notification"); - auto notificationNormalContent = std::make_shared(); - notificationNormalContent->SetText(content_); - notificationNormalContent->SetTitle(title_); - auto notificationContent = std::make_shared(notificationNormalContent); notificationRequest_ = new NotificationRequest(notificationId_); - notificationRequest_->SetLabel(NOTIFICATION_LABEL); - notificationRequest_->SetShowDeliveryTime(true); - notificationRequest_->SetSlotType(slotType_); - notificationRequest_->SetContent(notificationContent); - SetWantAgent(); // todo move to updateNotification + displayContent_ = content_; + AddActionButtons(true); +} + +bool ReminderRequest::IsAlerting() const +{ + return (state_ & REMINDER_STATUS_ALERTING) != 0; +} + +std::string ReminderRequest::GetDateTimeInfo(const time_t &timeInSecond) const +{ + struct tm *timeInfo; + timeInfo = localtime(&timeInSecond); + uint8_t dateTimeLen = 80; + char dateTimeBuffer[dateTimeLen]; + strftime(dateTimeBuffer, dateTimeLen, "%Y-%m-%d %H:%M:%S", timeInfo); + std::string dateTimeInfo(dateTimeBuffer); + return dateTimeInfo; +} + +uint64_t ReminderRequest::GetNowInstantMilli() const +{ + time_t now; + time(&now); // unit is seconds. + if (static_cast(now) < 0) { + ANSR_LOGE("Get now time error"); + return 0; + } + return static_cast(now * MILLI_SECONDS); +} + +std::string ReminderRequest::GetShowTime(const uint64_t showTime) const +{ + if (reminderType_ == ReminderType::TIMER) { + return ""; + } else { + struct tm *timeInfo; + const time_t showTimeInSecond = static_cast(showTime / 1000); + timeInfo = localtime(&showTimeInSecond); + uint8_t dateTimeLen = 80; + char dateTimeBuffer[dateTimeLen]; + strftime(dateTimeBuffer, dateTimeLen, "%H:%M", timeInfo); + std::string time = dateTimeBuffer; + return time; + } } std::string ReminderRequest::GetState(const uint8_t state) const { - std::string stateInfo = "Inactive"; + std::string stateInfo = "'"; if (state == REMINDER_STATUS_INACTIVE) { - return stateInfo; + stateInfo += "Inactive"; } else { + bool hasSeparator = false; + if ((state & REMINDER_STATUS_ACTIVE) != 0) { + stateInfo += "Active"; + hasSeparator = true; + } + if ((state & REMINDER_STATUS_ALERTING) != 0) { + if (hasSeparator) { + stateInfo += ","; + } + stateInfo += "Alerting"; + hasSeparator = true; + } if ((state & REMINDER_STATUS_SHOWING) != 0) { - stateInfo = "Showing"; + if (hasSeparator) { + stateInfo += ","; + } + stateInfo += "Showing"; + hasSeparator = true; + } + if ((state & REMINDER_STATUS_SNOOZE) != 0) { + if (hasSeparator) { + stateInfo += ","; + } + stateInfo += "Snooze"; } + stateInfo += "'"; } return stateInfo; } -void ReminderRequest::AddActionButtons() +void ReminderRequest::AddActionButtons(const bool includeSnooze) { int requestCode = 10; std::vector flags; @@ -562,6 +945,15 @@ void ReminderRequest::AddActionButtons() want->SetAction(REMINDER_EVENT_CLOSE_ALERT); ANSR_LOGD("Add action button, type is close"); } + if (type == ActionButtonType::SNOOZE) { + if (includeSnooze) { + want->SetAction(REMINDER_EVENT_SNOOZE_ALERT); + ANSR_LOGD("Add action button, type is snooze"); + } else { + ANSR_LOGD("Not add action button, type is snooze, as includeSnooze is false"); + continue; + } + } want->SetParam("REMINDER_ID", reminderId_); std::vector> wants; wants.push_back(want); @@ -602,13 +994,12 @@ void ReminderRequest::AddRemovalWantAgent() notificationRequest_->SetRemovalWantAgent(wantAgent); } -void ReminderRequest::SetWantAgent() +std::shared_ptr ReminderRequest::CreateWantAgent(AppExecFwk::ElementName &element) const { int requestCode = 10; std::vector flags; flags.push_back(WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); auto want = std::make_shared(); - AppExecFwk::ElementName element("", wantAgentInfo_->pkgName, wantAgentInfo_->abilityName); want->SetElement(element); std::vector> wants; wants.push_back(want); @@ -619,7 +1010,18 @@ void ReminderRequest::SetWantAgent() wants, nullptr ); - std::shared_ptr wantAgent = WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo); + return WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo); +} + +void ReminderRequest::SetMaxScreenWantAgent(AppExecFwk::ElementName &element) +{ + std::shared_ptr wantAgent = CreateWantAgent(element); + notificationRequest_->SetMaxScreenWantAgent(wantAgent); +} + +void ReminderRequest::SetWantAgent(AppExecFwk::ElementName &element) +{ + std::shared_ptr wantAgent = CreateWantAgent(element); notificationRequest_->SetWantAgent(wantAgent); } @@ -631,15 +1033,140 @@ void ReminderRequest::SetState(bool deSet, const uint8_t newState, std::string f } else { state_ &= ~newState; } - ANSR_LOGI("Switch the reminder(id=%{public}d) state, from %{public}s to %{public}s, called by %{public}s", + ANSR_LOGI("Switch the reminder(reminderId=%{public}d) state, from %{public}s to %{public}s, called by %{public}s", reminderId_, GetState(oldState).c_str(), GetState(state_).c_str(), function.c_str()); } +void ReminderRequest::UpdateActionButtons(const bool &setSnooze) +{ + if (notificationRequest_ == nullptr) { + ANSR_LOGE("updateActionButtons failed, the notificationRequest is null"); + return; + } + notificationRequest_->ClearActionButtons(); + if (setSnooze || snoozeTimesDynamic_ == snoozeTimes_) { + AddActionButtons(false); + } else { + AddActionButtons(true); + } +} + +bool ReminderRequest::UpdateNextReminder(const bool &force) +{ + bool result = true; + if (force) { + uint64_t nowInstantMilli = GetNowInstantMilli(); + if (nowInstantMilli == 0) { + result = false; + } else { + triggerTimeInMilli_ = nowInstantMilli + timeIntervalInMilli_; + snoozeTimesDynamic_ = snoozeTimes_; + if (timeIntervalInMilli_ != 0) { + isExpired_ = false; + } + } + } else { + result = UpdateNextReminder(); + } + std::string info = result == true ? "success" : "no next"; + ANSR_LOGI("updateNextReminder(id=%{public}d, %{public}s): force=%{public}d, trigger time is: %{public}s", + reminderId_, info.c_str(), force, + GetDateTimeInfo(static_cast(triggerTimeInMilli_ / MILLI_SECONDS)).c_str()); + return result; +} + void ReminderRequest::UpdateNotificationCommon() { + notificationRequest_->SetLabel(NOTIFICATION_LABEL); + notificationRequest_->SetShowDeliveryTime(true); + notificationRequest_->SetTapDismissed(true); + notificationRequest_->SetSlotType(slotType_); + auto notificationNormalContent = std::make_shared(); + notificationNormalContent->SetText(displayContent_); + notificationNormalContent->SetTitle(title_); + auto notificationContent = std::make_shared(notificationNormalContent); + notificationRequest_->SetContent(notificationContent); + if (reminderType_ == ReminderRequest::ReminderType::TIMER + || reminderType_ == ReminderRequest::ReminderType::ALARM) { + notificationRequest_->SetUnremovable(true); + } time_t now; (void)time(&now); // unit is seconds. notificationRequest_->SetDeliveryTime(static_cast(now * MILLI_SECONDS)); } + +void ReminderRequest::UpdateNotificationContent(const bool &setSnooze) +{ + if (notificationRequest_ == nullptr) { + ANSR_LOGE("updateNotificationContent failed, the notificationRequest is null"); + return; + } + std::string extendContent = ""; + if (setSnooze) { + if (timeIntervalInMilli_ != 0) { + // snooze the reminder by manual + extendContent = GetShowTime(triggerTimeInMilli_) + + snoozeContent_ == "" ? "" : (" (" + snoozeContent_ + ")"); + } else { + // the reminder is expired now, when timeInterval is 0 + extendContent = GetShowTime(reminderTimeInMilli_) + + expiredContent_ == "" ? "" : (" (" + expiredContent_ + ")"); + } + } else if (IsAlerting()) { + // the reminder is alerting, or ring duration is 0 + extendContent = GetShowTime(reminderTimeInMilli_); + } else if (snoozeTimesDynamic_ != snoozeTimes_) { + // the reminder is snoozing by period artithmetic, when the ring duration is over. + extendContent = GetShowTime(triggerTimeInMilli_) + + snoozeContent_ == "" ? "" : (" (" + snoozeContent_ + ")"); + notificationRequest_->SetTapDismissed(false); + } else { + // the reminder has already snoozed by period arithmetic, when the ring duration is over. + extendContent = GetShowTime(reminderTimeInMilli_) + + expiredContent_ == "" ? "" : (" (" + expiredContent_ + ")"); + } + displayContent_ = content_ + " " + extendContent; + ANSR_LOGD("Display content=%{public}s", displayContent_.c_str()); +} + +void ReminderRequest::UpdateNotificationStateForAlert() +{ + UpdateNotificationContent(false); + UpdateActionButtons(false); +} + +void ReminderRequest::UpdateNotificationStateForSnooze() +{ + UpdateNotificationContent(true); + UpdateActionButtons(true); +} + +int ReminderRequest::GetActualTime(const TimeTransferType &type, int cTime) +{ + switch (type) { + case (TimeTransferType::YEAR): // year + return BASE_YEAR + cTime; + case (TimeTransferType::MONTH): // month + return 1 + cTime; + case (TimeTransferType::WEEK): // week + return 1 + cTime; + default: + return -1; + } +} + +int ReminderRequest::GetCTime(const TimeTransferType &type, int actualTime) +{ + switch (type) { + case (TimeTransferType::YEAR): // year + return actualTime - BASE_YEAR; + case (TimeTransferType::MONTH): // month + return actualTime - 1; + case (TimeTransferType::WEEK): // week + return actualTime - 1; + default: + return -1; + } +} +} } -} \ No newline at end of file diff --git a/frameworks/ans/native/src/reminder_request_alarm.cpp b/frameworks/ans/native/src/reminder_request_alarm.cpp index 7cbc22645a58ed9763a0e5b0f5351e25c135938f..918736dcda011afe9670984dd4d8609d2a54e0a8 100644 --- a/frameworks/ans/native/src/reminder_request_alarm.cpp +++ b/frameworks/ans/native/src/reminder_request_alarm.cpp @@ -13,9 +13,10 @@ * limitations under the License. */ -#include "reminder_request_alarm.h" #include "ans_log_wrapper.h" +#include "reminder_request_alarm.h" + namespace OHOS { namespace Notification { const uint8_t ReminderRequestAlarm::DAYS_PER_WEEK = 7; @@ -25,10 +26,12 @@ const uint8_t ReminderRequestAlarm::HOURS_PER_DAY = 24; const uint16_t ReminderRequestAlarm::SECONDS_PER_HOUR = 3600; const uint8_t ReminderRequestAlarm::MINUTES_PER_HOUR = 60; const int8_t ReminderRequestAlarm::INVALID_INT_VALUE = -1; +const int8_t ReminderRequestAlarm::DEFAULT_SNOOZE_TIMES = 3; ReminderRequestAlarm::ReminderRequestAlarm(uint8_t hour, uint8_t minute, const std::vector daysOfWeek) : ReminderRequest(ReminderRequest::ReminderType::ALARM) { + SetSnoozeTimes(DEFAULT_SNOOZE_TIMES); hour_ = hour; minute_ = minute; CheckParamValid(); @@ -56,6 +59,15 @@ void ReminderRequestAlarm::CheckParamValid() const } } +bool ReminderRequestAlarm::IsRepeatReminder() const +{ + if ((repeatDays_ != 0) || ((GetTimeInterval() > 0) && (GetSnoozeTimes() > 0))) { + return true; + } else { + return false; + } +} + void ReminderRequestAlarm::SetDaysOfWeek(bool set, std::vector daysOfWeek) { if (daysOfWeek.size() == 0) { @@ -77,9 +89,13 @@ void ReminderRequestAlarm::SetDaysOfWeek(bool set, std::vector daysOfWe } } -uint64_t ReminderRequestAlarm::PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const +uint64_t ReminderRequestAlarm::PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const { - return GetNextTriggerTime(false); + if (ignoreRepeat || (repeatDays_)) { + return GetNextTriggerTime(forceToGetNext); + } else { + return INVALID_LONG_LONG_VALUE; + } } uint64_t ReminderRequestAlarm::GetNextTriggerTime(bool forceToGetNext) const @@ -95,13 +111,13 @@ uint64_t ReminderRequestAlarm::GetNextTriggerTime(bool forceToGetNext) const tar.tm_hour = hour_; tar.tm_min = minute_; tar.tm_sec = 0; + ANSR_LOGD("Now: year=%{public}d, mon=%{public}d, day=%{public}d, hour=%{public}d, " - "min=%{public}d, sec=%{public}d, week=%{public}d, tar_hour=%{public}d, tar_min=%{public}d", - nowTime->tm_year, nowTime->tm_mon, nowTime->tm_mday, nowTime->tm_hour, - nowTime->tm_min, nowTime->tm_sec, nowTime->tm_wday, hour_, minute_); - ANSR_LOGD("Tar: year=%{public}d, mon=%{public}d, day=%{public}d, hour=%{public}d, " - "min=%{public}d, sec=%{public}d, week=%{public}d", - tar.tm_year, tar.tm_mon, tar.tm_mday, tar.tm_hour, tar.tm_min, tar.tm_sec, tar.tm_wday); + "min=%{public}d, sec=%{public}d, week=%{public}d, \n Target: tar_hour=%{public}d, tar_min=%{public}d", + GetActualTime(TimeTransferType::YEAR, nowTime->tm_year), + GetActualTime(TimeTransferType::MONTH, nowTime->tm_mon), + nowTime->tm_mday, nowTime->tm_hour, nowTime->tm_min, nowTime->tm_sec, + GetActualTime(TimeTransferType::WEEK, nowTime->tm_wday), hour_, minute_); const time_t target = mktime(&tar); int8_t nextDayInterval = GetNextAlarm(now, target); @@ -120,8 +136,10 @@ uint64_t ReminderRequestAlarm::GetNextTriggerTime(bool forceToGetNext) const struct tm *test = localtime(&nextTriggerTime); ANSR_LOGI("NextTriggerTime: year=%{public}d, mon=%{public}d, day=%{public}d, hour=%{public}d, " "min=%{public}d, sec=%{public}d, week=%{public}d, nextTriggerTime=%{public}lld", - test->tm_year, test->tm_mon, test->tm_mday, test->tm_hour, test->tm_min, test->tm_sec, - test->tm_wday, (long long)nextTriggerTime); + GetActualTime(TimeTransferType::YEAR, test->tm_year), + GetActualTime(TimeTransferType::MONTH, test->tm_mon), + test->tm_mday, test->tm_hour, test->tm_min, test->tm_sec, + GetActualTime(TimeTransferType::WEEK, test->tm_wday), (long long)nextTriggerTime); if (static_cast(nextTriggerTime) <= 0) { return 0; @@ -192,18 +210,35 @@ bool ReminderRequestAlarm::OnTimeZoneChange() bool ReminderRequestAlarm::UpdateNextReminder() { - if (repeatDays_ == 0) { - ANSR_LOGD("Set reminder to expired"); - SetExpired(true); - return false; - } - uint64_t nextTriggerTime = GetNextTriggerTime(true); - if (nextTriggerTime != 0) { - ANSR_LOGI("Set next trigger time=%{public}llu", (unsigned long long)nextTriggerTime); - SetTriggerTimeInMilli(nextTriggerTime); + ANSR_LOGD("UpdateNextReminder alarm time"); + if (IsRepeatReminder()) { + uint8_t letfSnoozeTimes = GetSnoozeTimesDynamic(); + if ((letfSnoozeTimes > 0) && (GetTimeInterval() > 0)) { + ANSR_LOGI("Left times: %{public}d, update next triggerTime", GetSnoozeTimesDynamic()); + SetTriggerTimeInMilli(GetTriggerTimeInMilli() + GetTimeInterval() * MILLI_SECONDS); + SetSnoozeTimesDynamic(--letfSnoozeTimes); + } else { + SetSnoozeTimesDynamic(GetSnoozeTimes()); + if (repeatDays_ == 0) { + ANSR_LOGI("No need to update next triggerTime"); + SetExpired(true); + return false; + } else { + uint64_t nextTriggerTime = GetNextTriggerTime(true); + if (nextTriggerTime != INVALID_LONG_LONG_VALUE) { + ANSR_LOGI("Set next trigger time successful, reset dynamic snoozeTimes"); + SetTriggerTimeInMilli(nextTriggerTime); + } else { + ANSR_LOGW("Set reminder to expired"); + SetExpired(true); + return false; + } + } + } return true; } else { - ANSR_LOGD("Set reminder to expired"); + ANSR_LOGD("Single time reminder, not need to update next trigger time"); + SetSnoozeTimesDynamic(GetSnoozeTimes()); SetExpired(true); return false; } @@ -226,13 +261,11 @@ bool ReminderRequestAlarm::Marshalling(Parcel &parcel) const ANSR_LOGE("Failed to write daysOfWeek"); return false; } - return true; } ReminderRequestAlarm *ReminderRequestAlarm::Unmarshalling(Parcel &parcel) { - std::vector daysOfWeek; ANSR_LOGD("New alarm"); auto objptr = new ReminderRequestAlarm(); if ((objptr != nullptr) && !objptr->ReadFromParcel(parcel)) { diff --git a/frameworks/ans/native/src/reminder_request_calendar.cpp b/frameworks/ans/native/src/reminder_request_calendar.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42dbc301865d860c3b7bc68300c796a331299f87 --- /dev/null +++ b/frameworks/ans/native/src/reminder_request_calendar.cpp @@ -0,0 +1,481 @@ +/* + * 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. + */ + +#include "ans_log_wrapper.h" + +#include "reminder_request_calendar.h" + +namespace OHOS { +namespace Notification { +const uint8_t ReminderRequestCalendar::MAX_MONTHS_OF_YEAR = 12; +const uint8_t ReminderRequestCalendar::MAX_DAYS_OF_MONTH = 31; +const uint8_t ReminderRequestCalendar::JANUARY = 1; +const uint8_t ReminderRequestCalendar::DECEMBER = 12; +const uint8_t ReminderRequestCalendar::DEFAULT_SNOOZE_TIMES = 3; + +ReminderRequestCalendar::ReminderRequestCalendar(const tm &dateTime, + const std::vector &repeatMonths, const std::vector &repeatDays) : + ReminderRequest(ReminderRequest::ReminderType::CALENDAR) +{ + // 1. record the infomation which designated by user at first time. + firstDesignateYear_ = GetActualTime(TimeTransferType::YEAR, dateTime.tm_year); + firstDesignateMonth_ = GetActualTime(TimeTransferType::MONTH, dateTime.tm_mon); + firstDesignateDay_ = dateTime.tm_mday; + SetRepeatMonths(repeatMonths); + SetRepeatDaysOfMonth(repeatDays); + SetSnoozeTimes(DEFAULT_SNOOZE_TIMES); + + // 2. get the latest valid trigger time. + InitDateTime(dateTime); + hour_ = dateTime_.tm_hour; + minute_ = dateTime_.tm_min; + uint64_t nextTriggerTime = INVALID_LONG_LONG_VALUE; + if ((nextTriggerTime = GetNextTriggerTime()) != INVALID_LONG_LONG_VALUE) { + time_t target = static_cast(nextTriggerTime / MILLI_SECONDS); + dateTime_ = *(localtime(&target)); + } else { + ANSR_LOGW("Not exist next trigger time, please check the param of ReminderRequestCalendar constructor."); + throw std::invalid_argument( + "Not exist next trigger time, please check the param of ReminderRequestCalendar constructor."); + } + + // 2. set the time infomation (used to transfer to proxy service) which is decided to trigger firstly. + year_ = GetActualTime(TimeTransferType::YEAR, dateTime_.tm_year); + month_ = GetActualTime(TimeTransferType::MONTH, dateTime_.tm_mon); + day_ = dateTime_.tm_mday; + second_ = 0; + SetTriggerTimeInMilli(nextTriggerTime); +} + +ReminderRequestCalendar::ReminderRequestCalendar(const ReminderRequestCalendar &other) : ReminderRequest(other) +{ + dateTime_ = other.dateTime_; + firstDesignateYear_ = other.firstDesignateYear_; + firstDesignateMonth_ = other.firstDesignateMonth_; + firstDesignateDay_ = other.firstDesignateDay_; + year_ = other.year_; + month_ = other.month_; + day_ = other.day_; + hour_ = other.hour_; + minute_ = other.minute_; + second_ = other.second_; + repeatMonth_ = other.repeatMonth_; + repeatDay_ = other.repeatDay_; +} + +uint8_t ReminderRequestCalendar::GetDaysOfMonth(const uint16_t &year, const uint8_t &month) const +{ + uint8_t days; + uint8_t daysArray[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + uint8_t february = 2; + uint8_t leapMonth = 29; + uint8_t nonLeapMonth = 28; + if (month == february) { + days = ((((0 == year % 4) && (0 != year % 100)) || (0 == year % 400)) ? leapMonth : nonLeapMonth); + } else { + days = daysArray[month - 1]; + } + return days; +} + +uint8_t ReminderRequestCalendar::GetNextDay( + const uint16_t &settedYear, const uint8_t &settedMonth, const tm &now, const tm &target) const +{ + uint32_t repeatDayTmp = repeatDay_; + uint8_t daysOfSpecialMonth = GetDaysOfMonth(settedYear, settedMonth); + uint8_t setDayTmp = INVALID_U8_VALUE; + for (uint8_t i = 1; i <= daysOfSpecialMonth; i++) { + if ((repeatDayTmp & (1 << (i - 1))) > 0) { + struct tm setTime; + setTime.tm_year = GetCTime(TimeTransferType::YEAR, settedYear); + setTime.tm_mon = GetCTime(TimeTransferType::MONTH, settedMonth); + setTime.tm_mday = i; + setTime.tm_hour = target.tm_hour; + setTime.tm_min = target.tm_min; + setTime.tm_sec = target.tm_sec; + + struct tm nowTime; + nowTime.tm_year = now.tm_year; + nowTime.tm_mon = now.tm_mon; + nowTime.tm_mday = now.tm_mday; + nowTime.tm_hour = now.tm_hour; + nowTime.tm_min = now.tm_min; + nowTime.tm_sec = now.tm_sec; + if (mktime(&nowTime) >= mktime(&setTime)) { + continue; + } else { + setDayTmp = i; + return setDayTmp; + } + } + } + return setDayTmp; +} + +uint64_t ReminderRequestCalendar::GetNextTriggerTime() const +{ + uint64_t triggerTimeInMilli = INVALID_LONG_LONG_VALUE; + time_t now; + time(&now); // unit is seconds. + struct tm nowTime = *(localtime(&now)); + nowTime.tm_sec = 0; + struct tm tarTime; + tarTime.tm_year = GetCTime(TimeTransferType::YEAR, firstDesignateYear_); + tarTime.tm_mon = GetCTime(TimeTransferType::MONTH, firstDesignateMonth_); + tarTime.tm_mday = firstDesignateDay_; + tarTime.tm_hour = hour_; + tarTime.tm_min = minute_; + tarTime.tm_sec = 0; + + if (!(repeatMonth_ > 0 && repeatDay_ > 0)) { + const time_t target = mktime(&tarTime); + if (now <= target) { + triggerTimeInMilli = static_cast(target) * MILLI_SECONDS; + ANSR_LOGD("Now time is: %{public}s", GetDateTimeInfo(now).c_str()); + ANSR_LOGD("Tar time is: %{public}s", GetDateTimeInfo(target).c_str()); + } + return triggerTimeInMilli; + } + triggerTimeInMilli = GetNextTriggerTimeAsRepeatReminder(nowTime, tarTime); + return triggerTimeInMilli; +} + +uint64_t ReminderRequestCalendar::GetNextTriggerTimeAsRepeatReminder(const tm &nowTime, const tm &tarTime) const +{ + uint64_t triggerTimeInMilli = INVALID_LONG_LONG_VALUE; + uint16_t setYear = static_cast(GetActualTime(TimeTransferType::YEAR, nowTime.tm_year)); + uint8_t setMonth = INVALID_U8_VALUE; + uint8_t setDay = INVALID_U8_VALUE; + uint8_t beginMonth = static_cast(GetActualTime(TimeTransferType::MONTH, nowTime.tm_mon)); + uint8_t count = 1; + uint16_t repeatMonthTmp = repeatMonth_; + for (uint8_t i = beginMonth; i < (MAX_MONTHS_OF_YEAR + beginMonth + 1); i++) { + if ((repeatMonthTmp & (1 << ((i - 1) % MAX_MONTHS_OF_YEAR))) > 0) { + setMonth = (i % MAX_MONTHS_OF_YEAR); + setMonth = setMonth == 0 ? DECEMBER : setMonth; + if (count != 1) { + setYear = setMonth <= beginMonth ? setYear + 1 : setYear; + } + setDay = GetNextDay(setYear, setMonth, nowTime, tarTime); + } + if (setDay != INVALID_U8_VALUE) { + break; + } + count++; + } + if ((triggerTimeInMilli = GetTimeInstantMilli(setYear, setMonth, setDay, hour_, minute_, second_)) + != INVALID_LONG_LONG_VALUE) { + ANSR_LOGD("Next calendar time:%{public}u/%{public}u/%{public}u %{public}u:%{public}u:%{public}u", + setYear, setMonth, setDay, hour_, minute_, second_); + } + return triggerTimeInMilli; +} + +uint64_t ReminderRequestCalendar::GetTimeInstantMilli( + uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) const +{ + struct tm tar; + tar.tm_year = GetCTime(TimeTransferType::YEAR, year); + tar.tm_mon = GetCTime(TimeTransferType::MONTH, month); + tar.tm_mday = day; + tar.tm_hour = hour; + tar.tm_min = minute; + tar.tm_sec = second; + const time_t target = mktime(&tar); + if (target < 0) { + ANSR_LOGW("GetTImeInstantMilli less than 0."); + return INVALID_LONG_LONG_VALUE; + } + return static_cast(target) * MILLI_SECONDS; +} + +void ReminderRequestCalendar::InitDateTime() +{ + dateTime_.tm_year = GetCTime(TimeTransferType::YEAR, year_); + dateTime_.tm_mon = GetCTime(TimeTransferType::MONTH, month_); + dateTime_.tm_mday = day_; + dateTime_.tm_hour = hour_; + dateTime_.tm_min = minute_; + dateTime_.tm_sec = second_; +} + +void ReminderRequestCalendar::InitDateTime(const tm &dateTime) +{ + dateTime_.tm_year = dateTime.tm_year; + dateTime_.tm_mon = dateTime.tm_mon; + dateTime_.tm_mday = dateTime.tm_mday; + dateTime_.tm_hour = dateTime.tm_hour; + dateTime_.tm_min = dateTime.tm_min; + dateTime_.tm_sec = dateTime.tm_sec; +} + +bool ReminderRequestCalendar::IsRepeatReminder() const +{ + return (repeatMonth_ > 0 && repeatDay_ > 0) || (GetTimeInterval() > 0 && GetSnoozeTimes() > 0); +} + + +bool ReminderRequestCalendar::IsRepeatMonth(uint8_t month) const +{ + return (repeatMonth_ & (1 << (month - 1))) > 0; +} + +bool ReminderRequestCalendar::IsRepeatDay(uint8_t day) const{ + return (repeatDay_ & (1 << (day - 1))) > 0; +} + +void ReminderRequestCalendar::SetDay(const uint8_t &day, const bool &isSet) +{ + if (day < 1 || day > MAX_DAYS_OF_MONTH) { + return; + } + if (isSet) { + repeatDay_ |= 1 << (day - 1); + } else { + repeatDay_ &= ~(1 << (day - 1)); + } +} + +void ReminderRequestCalendar::SetMonth(const uint8_t &month, const bool &isSet) +{ + if (month < JANUARY || month > DECEMBER) { + return; + } + if (isSet) { + repeatMonth_ |= 1 << (month - 1); + } else { + repeatMonth_ &= ~ (1 << (month - 1)); + } +} + +void ReminderRequestCalendar::SetRepeatMonths(const std::vector &repeatMonths) +{ + if (repeatMonths.size() > MAX_MONTHS_OF_YEAR) { + ANSR_LOGW("The length of repeat months array should not larger than %{public}u", MAX_MONTHS_OF_YEAR); + throw std::invalid_argument( + "The length of repeat months array should not larger than " + std::to_string(MAX_MONTHS_OF_YEAR)); + } + repeatMonth_ = 0; + for (auto it = repeatMonths.begin(); it != repeatMonths.end(); ++it) { + SetMonth((*it), true); + } +} + +void ReminderRequestCalendar::SetRepeatDaysOfMonth(const std::vector &repeateDays) +{ + if (repeateDays.size() > MAX_DAYS_OF_MONTH) { + ANSR_LOGW("The length of repeat days array should not larger than %{public}u", MAX_DAYS_OF_MONTH); + throw std::invalid_argument( + "The length of repeat days array should not larger than " + std::to_string(MAX_DAYS_OF_MONTH)); + } + repeatDay_ = 0; + for (auto it = repeateDays.begin(); it != repeateDays.end(); ++it) { + SetDay((*it), true); + } +} + +std::vector ReminderRequestCalendar::GetRepeatMonths() const +{ + std::vector repeatMonths; + for (int i = 0; i < 12; i++) { + if (IsRepeatMonth(i + 1)) { + repeatMonths.push_back(i + 1); + } + } + return repeatMonths; +} + +std::vector ReminderRequestCalendar::GetRepeatDays() const +{ + std::vector repeatDays; + for (int i = 0; i < 31; i++) { + if (IsRepeatDay(i + 1)) { + repeatDays.push_back(i + 1); + } + } + return repeatDays; +} + +bool ReminderRequestCalendar::OnDateTimeChange() +{ + return ReminderRequest::OnDateTimeChange(); +} + +bool ReminderRequestCalendar::OnTimeZoneChange() +{ + return ReminderRequest::OnTimeZoneChange(); +} + +bool ReminderRequestCalendar::UpdateNextReminder() +{ + ANSR_LOGD("UpdateNextReminder calendar time"); + if (!IsRepeatReminder()) { + ANSR_LOGI("No need to update next trigger time as it is an one-time reminder."); + SetSnoozeTimesDynamic(GetSnoozeTimes()); + SetExpired(true); + return false; + } + uint8_t leftSnoozeTimes = GetSnoozeTimesDynamic(); + if (leftSnoozeTimes > 0 && (GetTimeInterval() > 0)) { + ANSR_LOGI("Left snooze times: %{public}d, update next triggerTime", leftSnoozeTimes); + SetTriggerTimeInMilli(GetTriggerTimeInMilli() + GetTimeInterval() * MILLI_SECONDS); + SetSnoozeTimesDynamic(--leftSnoozeTimes); + } else { + SetSnoozeTimesDynamic(GetSnoozeTimes()); + if (repeatMonth_ == 0 || repeatDay_ == 0) { + ANSR_LOGI("Not a day repeat reminder, no need to update to next trigger time."); + SetExpired(true); + return false; + } else { + uint64_t nextTriggerTime = GetNextTriggerTime(); + if (nextTriggerTime != INVALID_LONG_LONG_VALUE) { + ANSR_LOGI("Set next trigger time successful, reset dynamic snoozeTimes"); + SetTriggerTimeInMilli(nextTriggerTime); + } else { + ANSR_LOGW("Set next trigger time invalidate"); + SetExpired(true); + return false; + } + } + } + return true; +} + +uint64_t ReminderRequestCalendar::PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const +{ + if (ignoreRepeat || (repeatMonth_ > 0 && repeatDay_ > 0)) { + return GetNextTriggerTime(); + } else { + return INVALID_LONG_LONG_VALUE; + } +} + +bool ReminderRequestCalendar::Marshalling(Parcel &parcel) const +{ + ReminderRequest::Marshalling(parcel); + + // write int + if (!parcel.WriteUint16(year_)) { + ANSR_LOGE("Failed to write year"); + return false; + } + if (!parcel.WriteUint8(month_)) { + ANSR_LOGE("Failed to write month"); + return false; + } + if (!parcel.WriteUint8(day_)) { + ANSR_LOGE("Failed to write day"); + return false; + } + if (!parcel.WriteUint8(hour_)) { + ANSR_LOGE("Failed to write hour"); + return false; + } + if (!parcel.WriteUint8(minute_)) { + ANSR_LOGE("Failed to write minute"); + return false; + } + if (!parcel.WriteUint8(second_)) { + ANSR_LOGE("Failed to write second"); + return false; + } + if (!parcel.WriteUint16(repeatMonth_)) { + ANSR_LOGE("Failed to write repeatMonth"); + return false; + } + if (!parcel.WriteUint32(repeatDay_)) { + ANSR_LOGE("Failed to write repeateDay"); + return false; + } + if (!parcel.WriteUint16(firstDesignateYear_)) { + ANSR_LOGE("Failed to write firstDesignateYear"); + return false; + } + if (!parcel.WriteUint8(firstDesignateMonth_)) { + ANSR_LOGE("Failed to write firstDesignateMonth"); + return false; + } + if (!parcel.WriteUint8(firstDesignateDay_)) { + ANSR_LOGE("Failed to write firstDesignateDay"); + return false; + } + return true; +} + +ReminderRequestCalendar *ReminderRequestCalendar::Unmarshalling(Parcel &parcel) +{ + ANSR_LOGD("New calendar"); + auto objptr = new ReminderRequestCalendar(); + if ((objptr != nullptr) && !objptr->ReadFromParcel(parcel)) { + delete objptr; + objptr = nullptr; + } + return objptr; +} + +bool ReminderRequestCalendar::ReadFromParcel(Parcel &parcel) +{ + ReminderRequest::ReadFromParcel(parcel); + + // read int + if (!parcel.ReadUint16(year_)) { + ANSR_LOGE("Failed to read year"); + return false; + } + if (!parcel.ReadUint8(month_)) { + ANSR_LOGE("Failed to read month"); + return false; + } + if (!parcel.ReadUint8(day_)) { + ANSR_LOGE("Failed to read day"); + return false; + } + if (!parcel.ReadUint8(hour_)) { + ANSR_LOGE("Failed to read hour"); + return false; + } + if (!parcel.ReadUint8(minute_)) { + ANSR_LOGE("Failed to read minute"); + return false; + } + if (!parcel.ReadUint8(second_)) { + ANSR_LOGE("Failed to read second"); + return false; + } + if (!parcel.ReadUint16(repeatMonth_)) { + ANSR_LOGE("Failed to read repeatMonth"); + return false; + } + if (!parcel.ReadUint32(repeatDay_)) { + ANSR_LOGE("Failed to read repeateDay"); + return false; + } + InitDateTime(); + if (!parcel.ReadUint16(firstDesignateYear_)) { + ANSR_LOGE("Failed to read firstDesignateYear"); + return false; + } + if (!parcel.ReadUint8(firstDesignateMonth_)) { + ANSR_LOGE("Failed to read firstDesignateMonth"); + return false; + } + if (!parcel.ReadUint8(firstDesignateDay_)) { + ANSR_LOGE("Failed to read firstDesignateDay"); + return false; + } + return true; +} +} +} \ No newline at end of file diff --git a/frameworks/ans/native/src/reminder_request_timer.cpp b/frameworks/ans/native/src/reminder_request_timer.cpp index 00b975cc7220f3f3dac2370d35cb9f5a37ef7d2c..773e18eba07ce3027e5ceb3d9bddeac6e0737ebc 100644 --- a/frameworks/ans/native/src/reminder_request_timer.cpp +++ b/frameworks/ans/native/src/reminder_request_timer.cpp @@ -47,10 +47,10 @@ uint64_t ReminderRequestTimer::GetInitInfo() const return countDownTimeInSeconds_; } -uint64_t ReminderRequestTimer::PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const +uint64_t ReminderRequestTimer::PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const { ANSR_LOGD("countdonw time not support PreGetNextTriggerTimeIgnoreSnooze"); - return ReminderRequest::INVALID_LONG_VALUE; + return ReminderRequest::INVALID_LONG_LONG_VALUE; } bool ReminderRequestTimer::OnDateTimeChange() diff --git a/frameworks/ans/native/test/unittest/reminder_request_test.cpp b/frameworks/ans/native/test/unittest/reminder_request_test.cpp index 0be99c93927a940a98839f25d30ed9969e19aa24..1f189e9f55060ad7f53a7217e90b21a0d43b694d 100644 --- a/frameworks/ans/native/test/unittest/reminder_request_test.cpp +++ b/frameworks/ans/native/test/unittest/reminder_request_test.cpp @@ -56,7 +56,7 @@ HWTEST_F(ReminderRequestTest, CanRemove_00100, Function | SmallTest | Level1) HWTEST_F(ReminderRequestTest, CanRemove_00200, Function | SmallTest | Level1) { auto rrc = std::make_shared(); - rrc->OnShow(false, true); + rrc->OnShow(false, false, true); EXPECT_FALSE(rrc->CanRemove()) << "When shown, canRemove should be false"; } @@ -68,7 +68,7 @@ HWTEST_F(ReminderRequestTest, CanRemove_00200, Function | SmallTest | Level1) HWTEST_F(ReminderRequestTest, CanRemove_00300, Function | SmallTest | Level1) { auto rrc = std::make_shared(); - rrc->OnShow(false, true); + rrc->OnShow(false, false, true); rrc->OnClose(false); EXPECT_TRUE(rrc->CanRemove()) << "When reminder is expired and closed, can remove should be false"; } @@ -81,7 +81,7 @@ HWTEST_F(ReminderRequestTest, CanRemove_00300, Function | SmallTest | Level1) HWTEST_F(ReminderRequestTest, CanRemove_00400, Function | SmallTest | Level1) { auto rrc = std::make_shared(); - rrc->OnShow(false, true); + rrc->OnShow(false, false, true); rrc->OnSameNotificationIdCovered(); EXPECT_TRUE(rrc->CanRemove()) << "When reminder is expired and covered by \ sameNotification id, can remove should be true"; @@ -142,7 +142,7 @@ HWTEST_F(ReminderRequestTest, StateCheck_00400, Function | SmallTest | Level1) HWTEST_F(ReminderRequestTest, StateCheck_00500, Function | SmallTest | Level1) { auto rrc = std::make_shared(); - rrc->OnShow(true, true); + rrc->OnShow(false, true, true); EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) != 0); } @@ -154,7 +154,7 @@ HWTEST_F(ReminderRequestTest, StateCheck_00500, Function | SmallTest | Level1) HWTEST_F(ReminderRequestTest, StateCheck_00600, Function | SmallTest | Level1) { auto rrc = std::make_shared(); - rrc->OnShow(false, true); + rrc->OnShow(false, false, true); EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) != 0); } @@ -167,7 +167,7 @@ HWTEST_F(ReminderRequestTest, StateCheck_00700, Function | SmallTest | Level1) { auto rrc = std::make_shared(); uint8_t stateBefore = rrc->GetState(); - rrc->OnShow(true, false); + rrc->OnShow(false, true, false); EXPECT_EQ(rrc->GetState(), stateBefore); } @@ -180,7 +180,7 @@ HWTEST_F(ReminderRequestTest, StateCheck_00800, Function | SmallTest | Level1) { auto rrc = std::make_shared(); uint8_t stateBefore = rrc->GetState(); - rrc->OnShow(false, false); + rrc->OnShow(false, false, false); EXPECT_EQ(rrc->GetState(), stateBefore); } diff --git a/frameworks/ans/test/moduletest/BUILD.gn b/frameworks/ans/test/moduletest/BUILD.gn index 9c8579d91c3f72edf0fe4573c9cf8d8f58f265e0..2c117a4cf12146992560bf15dd1709e57312b30f 100644 --- a/frameworks/ans/test/moduletest/BUILD.gn +++ b/frameworks/ans/test/moduletest/BUILD.gn @@ -346,5 +346,6 @@ group("moduletest") { ":ans_innerkits_module_publish_test", ":ans_innerkits_module_setting_test", ":ans_innerkits_module_slot_test", + ":ReminderAgentTest", ] } diff --git a/interfaces/innerkits/ans/native/include/reminder_request.h b/interfaces/innerkits/ans/native/include/reminder_request.h index 87445ac4c5c6d2a58c47a3773f6bc1d932958581..65b4ff19320dedfb20bd432d3b0a43d9f89524c1 100644 --- a/interfaces/innerkits/ans/native/include/reminder_request.h +++ b/interfaces/innerkits/ans/native/include/reminder_request.h @@ -72,11 +72,21 @@ public: */ enum class UpdateNotificationType : uint8_t { COMMON, - ACTION_BUTTON, REMOVAL_WANT_AGENT, + WANT_AGENT, + MAX_SCREEN_WANT_AGENT, CONTENT }; + /** + * @brief Enumerates the Time type for converting between c time and acture time. + */ + enum class TimeTransferType : uint8_t { + YEAR, + MONTH, + WEEK + }; + /** * @brief Attributes of action button. */ @@ -100,6 +110,11 @@ public: std::string abilityName = ""; }; + struct MaxScreenAgentInfo { + std::string pkgName = ""; + std::string abilityName = ""; + }; + /** * @brief Copy construct from an exist reminder. * @@ -131,6 +146,8 @@ public: */ bool CanRemove(); + bool CanShow() const; + /** * @brief Obtains all the information of the reminder. * @@ -159,6 +176,8 @@ public: */ std::string GetExpiredContent() const; + std::shared_ptr GetMaxScreenWantAgentInfo() const; + /** * @brief Obtains notification id. * @@ -180,6 +199,8 @@ public: */ int32_t GetReminderId() const; + uint64_t GetReminderTimeInMilli() const; + /** * @brief Obtains reminder type. * @@ -187,6 +208,13 @@ public: */ ReminderType GetReminderType() const; + /** + * @brief Obtains the ringing or vibration duration configured for this reminder. + * + * @return uint16_t The ringing or vibration duration in seconds. + */ + uint16_t GetRingDuration() const; + /** * @brief Obtains slot type. * @@ -194,8 +222,18 @@ public: */ NotificationConstant::SlotType GetSlotType() const; + std::string GetSnoozeContent() const; + uint8_t GetSnoozeTimes() const; + uint8_t GetSnoozeTimesDynamic() const; uint8_t GetState() const; + /** + * @brief Obtains the Time Interval in seconds. + * + * @return uint64_t Time Interval in seconds. + */ + uint64_t GetTimeInterval() const; + /** * @brief Obtains title. * @@ -223,6 +261,13 @@ public: */ void InitReminderId(); + /** + * @brief Check the reminder is alerting or not. + * + * @return true if the reminder is playing sound or vibrating. + */ + bool IsAlerting() const; + /** * @brief Check the reminder is expired or not. * @@ -260,10 +305,16 @@ public: /** * @brief Show the reminder on panel. TriggerTime will be updated to next. * + * @param isPlaySoundOrVibration true means it is play sound or vibration. * @param isSysTimeChanged true means it is called when the system time is changed by user, otherwise false. * @param allowToNotify true means that the notification will be shown as normal, otherwise false. */ - void OnShow(bool isSysTimeChanged, bool allowToNotify); + void OnShow(bool isPlaySoundOrVibration, bool isSysTimeChanged, bool allowToNotify); + void OnShowFail(); + bool OnSnooze(); + void OnStart(); + void OnStop(); + bool OnTerminate(); /** * @brief When timezone change, reminder need to refresh next trigger time. @@ -304,6 +355,8 @@ public: */ ReminderRequest& SetExpiredContent(const std::string &expiredContent); + ReminderRequest& SetMaxScreenWantAgentInfo(const std::shared_ptr &maxScreenWantAgentInfo); + /** * @brief Sets notification id. * @@ -319,6 +372,16 @@ public: */ void SetReminderId(int32_t reminderId); + void SetReminderTimeInMilli(const uint64_t reminderTimeInMilli); + + /** + * @brief Sets the ringing or vibration duration for this reminder, in seconds. + * + * @param ringDurationInSeconds Indicates the duration. The defautl is 1 second. + * @return Current reminder self. + */ + ReminderRequest& SetRingDuration(const uint64_t ringDurationInSeconds); + /** * @brief Sets slot type. * @@ -327,6 +390,41 @@ public: */ ReminderRequest& SetSlotType(const NotificationConstant::SlotType &slotType); + ReminderRequest& SetSnoozeContent(const std::string &snoozeContent); + + /** + * @brief Set the number of snooze times for this reminder. + * + * @note If the value of snoozeTimes is less than or equals to 0, this reminder is a one-shot + * reminder and will not be snoozed. + * + * It the value of snoozeTimes is greater than 0, for example, snoozeTimes=3, this reminder + * will be snoozed three times after the first alarm, that is, this reminder will be triggered + * for four times. + * + * This method does not take affect on the reminders for countdown timers. + * + * @param snoozeTimes Indicates the number of times that the reminder will be snoozed. + * @return ReminderRequest& Current reminder self. + */ + ReminderRequest& SetSnoozeTimes(const uint8_t snoozeTimes); + + ReminderRequest& SetSnoozeTimesDynamic(const uint8_t snooziTimes); + + /** + * @brief Sets the Time Interval for this reminder, in seconds. The default value is 0. + * + * @note The minimum snooze interval is 5 minute. If the snooze interval is set to a value greater + * than 0 and less than 5 minutes, the system converts it to 5 minutes by default. + * + * This method does not take effect on the reminders for countdown timers. + * + * @param timeIntervalInSeconds Indicates the snooze interval to set. If the value is less or equals to 0, + * the reminder will not be snoozed. + * @return ReminderRequest& Current reminder self. + */ + ReminderRequest& SetTimeInterval(const uint64_t timeIntervalInSeconds); + /** * @brief Sets title. * @@ -350,6 +448,8 @@ public: */ ReminderRequest& SetWantAgentInfo(const std::shared_ptr &wantAgentInfo); + bool ShouldShowImmediately() const; + /** * @brief Updates {@link triggerTimeInMilli_} to next. * @note If next trigger time not exist, {@link isExpired_} flag will be set with true. @@ -371,7 +471,9 @@ public: void UpdateNotificationRequest(UpdateNotificationType type, std::string extra); static int32_t GLOBAL_ID; - static const uint64_t INVALID_LONG_VALUE; + static const uint64_t INVALID_LONG_LONG_VALUE; + static const uint16_t INVALID_U16_VALUE; + static const uint8_t INVALID_U8_VALUE; static const uint16_t MILLI_SECONDS; static const uint16_t SAME_TIME_DISTINGUISH_MILLISECONDS; static const std::string NOTIFICATION_LABEL; @@ -401,41 +503,80 @@ public: */ static const std::string REMINDER_EVENT_REMOVE_NOTIFICATION; static const std::string PARAM_REMINDER_ID; + static int GetActualTime(const TimeTransferType &type, int cTime); + static int GetCTime(const TimeTransferType &type, int actualTime); protected: ReminderRequest(); explicit ReminderRequest(ReminderType reminderType); - virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const - { - return INVALID_LONG_VALUE; + std::string GetDateTimeInfo(const time_t &timeInSecond) const; + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const { + return INVALID_LONG_LONG_VALUE; } + static const int BASE_YEAR; private: - void AddActionButtons(); + void AddActionButtons(const bool includeSnooze); void AddRemovalWantAgent(); + std::shared_ptr CreateWantAgent(AppExecFwk::ElementName &element) const; + uint64_t GetNowInstantMilli() const; + std::string GetShowTime(const uint64_t showTime) const; std::string GetState(const uint8_t state) const; bool HandleSysTimeChange(uint64_t oriTriggerTime, uint64_t optTriggerTime); bool HandleTimeZoneChange(uint64_t oldZoneTriggerTime, uint64_t newZoneTriggerTime, uint64_t optTriggerTime); void InitNotificationRequest(); + void SetMaxScreenWantAgent(AppExecFwk::ElementName &element); void SetState(bool deSet, const uint8_t newState, std::string function); - void SetWantAgent(); + void SetWantAgent(AppExecFwk::ElementName &element); + void UpdateActionButtons(const bool &setSnooze); + bool UpdateNextReminder(const bool &force); + void UpdateNotificationContent(const bool &setSnooze); void UpdateNotificationCommon(); + /** + * @brief Update the notification, which will be shown for the "Alerting" reminder. + * 1. Update the notification label/content. + * 2. Restore the snooze action button. + */ + void UpdateNotificationStateForAlert(); + + /** + * @brief Update the notification, which will be shown when user do a snooze. + * 1. Update the notification label/content. + * 2. Remove the snooze action button. + */ + void UpdateNotificationStateForSnooze(); + static const uint8_t REMINDER_STATUS_INACTIVE; + static const uint8_t REMINDER_STATUS_ACTIVE; + static const uint8_t REMINDER_STATUS_ALERTING; static const uint8_t REMINDER_STATUS_SHOWING; + static const uint8_t REMINDER_STATUS_SNOOZE; + static const uint32_t MIN_TIME_INTERVAL_IN_MILLI; std::string content_ {}; std::string expiredContent_ {}; + std::string snoozeContent_ {}; + std::string displayContent_ {}; std::string title_ {}; bool isExpired_ {false}; + uint8_t snoozeTimes_ {0}; + uint8_t snoozeTimesDynamic_ {0}; uint8_t state_ {0}; int32_t notificationId_ {0}; int32_t reminderId_ {-1}; + + // Indicates the reminder has been shown in the past time. + // When the reminder has been created but not showed, it is equals to 0. + uint64_t reminderTimeInMilli_ {0}; + uint64_t ringDurationInMilli_ {MILLI_SECONDS}; uint64_t triggerTimeInMilli_ {0}; + uint64_t timeIntervalInMilli_ {0}; ReminderType reminderType_ {ReminderType::INVALID}; NotificationConstant::SlotType slotType_ {NotificationConstant::SlotType::SOCIAL_COMMUNICATION}; sptr notificationRequest_ = nullptr; std::shared_ptr wantAgentInfo_ = nullptr; + std::shared_ptr maxScreenWantAgentInfo_ = nullptr; std::map actionButtonMap_ {}; }; } // namespace Reminder diff --git a/interfaces/innerkits/ans/native/include/reminder_request_alarm.h b/interfaces/innerkits/ans/native/include/reminder_request_alarm.h index e05550d84071017d574b4622b643bdc4f827306f..5d7471eff85ddffe8bb9db3f6e978657f2803ad1 100644 --- a/interfaces/innerkits/ans/native/include/reminder_request_alarm.h +++ b/interfaces/innerkits/ans/native/include/reminder_request_alarm.h @@ -98,7 +98,7 @@ public: bool ReadFromParcel(Parcel &parcel) override; protected: - virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const override; + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const override; private: ReminderRequestAlarm() : ReminderRequest() {}; @@ -124,6 +124,7 @@ private: * @return true if it is a repeat day. */ bool IsRepeatDay(int day) const; + bool IsRepeatReminder() const; void SetDaysOfWeek(bool set, std::vector daysOfWeek); /** @@ -142,6 +143,7 @@ private: static const uint16_t SECONDS_PER_HOUR; static const uint8_t MINUTES_PER_HOUR; static const int8_t INVALID_INT_VALUE; + static const int8_t DEFAULT_SNOOZE_TIMES; uint8_t hour_ = {0}; uint8_t minute_ = {0}; diff --git a/interfaces/innerkits/ans/native/include/reminder_request_calendar.h b/interfaces/innerkits/ans/native/include/reminder_request_calendar.h new file mode 100644 index 0000000000000000000000000000000000000000..c7f132e83f4926e75ddaee864880e80394c8b815 --- /dev/null +++ b/interfaces/innerkits/ans/native/include/reminder_request_calendar.h @@ -0,0 +1,169 @@ +/* + * 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_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_CALENDAR_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_CALENDAR_H + +#include "reminder_request.h" + +#include + +namespace OHOS { +namespace Notification { +class ReminderRequestCalendar : public ReminderRequest { +public: + /** + * @brief A {@link ReminderRequest} child class used for creating reminders of calendar clocks. + * + * @note The params must meet the following conditions. + * otherwise the application may crash due to an illegal parameter exception. + *
    + *
  • The length of repeatMonths vectory cannot exceed 12.
  • + *
  • The length of repeateDays vectory cannot exceed 31.
  • + *
  • There must be at least one valid reminder time. Ensure that the time specified by dateTime + * does not expired, or repeatMonths and repeateDays are valid.
  • + *
+ * + * The repeateMonths and repeatDays must both be set to implements repeated reminders. + * By default, this reminder is not snoozed. You can call {@link SetTimeInterval} to + * set the snooze interval. + * + * @param dateTime Indicates the date and time when this calendar event reminder will be triggered. + * The time is accurate to minute. For example, the value + * {@link LocalDateTime(2021, 3, 3, 16, 15)} indicates that the reminder will be + * triggered at 16:15 on March 3, 2021. + * @param repeatMonths Indicates the months in which this reminder will be repeated. For example, + * the value {2, 4} indicates that the reminder will be triggered on particular + * days in February and April. + * @param repeatDays Indicates the days in a month when this reminder will be repeated. For example, + * the value {2, 4} indicates that the reminder will be triggered on the second + * and fourth day of the specific months. + */ + ReminderRequestCalendar(const tm &dateTime, + const std::vector &repeatMonths, const std::vector &repeatDays); + + explicit ReminderRequestCalendar(const ReminderRequestCalendar &other); + ReminderRequestCalendar& operator = (const ReminderRequestCalendar &other); + ~ReminderRequestCalendar() {} + + inline uint16_t GetYear() const + { + return year_; + } + + inline uint8_t GetMonth() const + { + return month_; + } + + inline uint8_t GetDay() const + { + return day_; + } + + inline uint8_t GetHour() const + { + return hour_; + } + + inline uint8_t GetMinute() const + { + return minute_; + } + + inline uint8_t GetSecond() const + { + return second_; + } + + std::vector GetRepeatMonths() const; + std::vector GetRepeatDays() const; + + virtual bool OnDateTimeChange() override; + virtual bool OnTimeZoneChange() override; + virtual bool UpdateNextReminder() override; + + /** + * Marshal a reminder object into a Parcel. + * + * @param parcel Indicates the Parcel. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * Unmarshal object from a Parcel. + * + * @param parcel Indicates the Parcel. + * @return reminder object. + */ + static ReminderRequestCalendar *Unmarshalling(Parcel &parcel); + + /** + * Unmarshal unique properties of alarm from a Parcel. + * + * @param parcel Indicates the Parcel. + * @return true if read parcel success. + */ + bool ReadFromParcel(Parcel &parcel) override; + + static const uint8_t MAX_MONTHS_OF_YEAR; + static const uint8_t MAX_DAYS_OF_MONTH; + +protected: + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const override; + +private: + ReminderRequestCalendar() : ReminderRequest() {} + + uint8_t GetDaysOfMonth(const uint16_t &year, const uint8_t &month) const; + uint8_t GetNextDay(const uint16_t &settedYear, const uint8_t &settedMonth, const tm &now, const tm &target) const; + uint64_t GetNextTriggerTime() const; + uint64_t GetNextTriggerTimeAsRepeatReminder(const tm &nowTime, const tm &tarTime) const; + uint64_t GetTimeInstantMilli( + uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) const; + + /** + * @brief Init dateTime_ when read from parcel. + */ + void InitDateTime(); + void InitDateTime(const tm &dateTime); + bool IsRepeatReminder() const; + bool IsRepeatMonth(uint8_t month) const; + bool IsRepeatDay(uint8_t day) const; + void SetDay(const uint8_t &day, const bool &isSet); + void SetMonth(const uint8_t &month, const bool &isSet); + void SetRepeatMonths(const std::vector &repeatMonths); + void SetRepeatDaysOfMonth(const std::vector &repeateDays); + + static const uint8_t JANUARY; + static const uint8_t DECEMBER; + static const uint8_t DEFAULT_SNOOZE_TIMES; + + tm dateTime_; + uint16_t firstDesignateYear_ {1}; + uint8_t firstDesignateMonth_ {1}; + uint8_t firstDesignateDay_ {1}; + uint16_t year_ {1}; + uint8_t month_ {1}; + uint8_t day_ {1}; + uint8_t hour_ {1}; + uint8_t minute_ {1}; + uint8_t second_ {0}; + uint16_t repeatMonth_; + uint32_t repeatDay_; +}; +} +} +#endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_CALENDAR_H \ No newline at end of file diff --git a/interfaces/innerkits/ans/native/include/reminder_request_timer.h b/interfaces/innerkits/ans/native/include/reminder_request_timer.h index 03705509c9da7c9702e17bb3cf141ae194b1cd16..a33c0142e0ad98eaa8dfe739dd97a711abc4fe0a 100644 --- a/interfaces/innerkits/ans/native/include/reminder_request_timer.h +++ b/interfaces/innerkits/ans/native/include/reminder_request_timer.h @@ -62,7 +62,7 @@ public: bool ReadFromParcel(Parcel &parcel) override; protected: - virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const override; + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool ignoreRepeat, bool forceToGetNext) const override; private: ReminderRequestTimer() {}; diff --git a/interfaces/kits/napi/ans/include/reminder/reminder_common.h b/interfaces/kits/napi/ans/include/reminder/reminder_common.h index 0f9b9e057ceacfacdd74ca6a15bb5a24e71dd99e..63b1d0f796e16be16994fb08cf4814b07b22c48d 100644 --- a/interfaces/kits/napi/ans/include/reminder/reminder_common.h +++ b/interfaces/kits/napi/ans/include/reminder/reminder_common.h @@ -26,22 +26,38 @@ namespace ReminderAgentNapi { using namespace OHOS::Notification; namespace { -const char* REMINDER_TYPE = "reminderType"; -const char* ALARM_HOUR = "hour"; -const char* ALARM_MINUTE = "minute"; -const char* ALARM_DAYS_OF_WEEK = "daysOfWeek"; -const char* TIMER_COUNT_DOWN_TIME = "triggerTimeInSeconds"; const char* ACTION_BUTTON = "actionButton"; const char* ACTION_BUTTON_TITLE = "title"; const char* ACTION_BUTTON_TYPE = "type"; -const char* WANT_AGENT = "wantAgent"; -const char* WANT_AGENT_PKG = "pkgName"; -const char* WANT_AGENT_ABILITY = "abilityName"; -const char* TITLE = "title"; +const char* ALARM_HOUR = "hour"; +const char* ALARM_DAYS_OF_WEEK = "daysOfWeek"; +const char* ALARM_MINUTE = "minute"; +const char* CALENDAR_DATE_TIME = "dateTime"; +const char* CALENDAR_YEAR = "year"; +const char* CALENDAR_MONTH = "month"; +const char* CALENDAR_DAY = "day"; +const char* CALENDAR_HOUR = "hour"; +const char* CALENDAR_MINUTE = "minute"; +const char* CALENDAR_SECOND = "second"; +const char* CALENDAR_REPEAT_MONTHS = "repeatMonths"; +const char* CALENDAR_REPEAT_DAYS = "repeatDays"; const char* CONTENT = "content"; const char* EXPIRED_CONTENT = "expiredContent"; +const char* MAX_SCREEN_WANT_AGENT = "maxScreenWantAgent"; +const char* MAX_SCREEN_WANT_AGENT_PKG = "pkgName"; +const char* MAX_SCREEN_WANT_AGENT_ABILITY = "abilityName"; const char* NOTIFICATION_ID = "notificationId"; +const char* REMINDER_TYPE = "reminderType"; +const char* RING_DURATION = "ringDuration"; const char* SLOT_TYPE = "slotType"; +const char* SNOOZE_CONTENT = "snoozeContent"; +const char* SNOOZE_TIMES = "snoozeTimes"; +const char* TIME_INTERVAL = "timeInterval"; +const char* TITLE = "title"; +const char* TIMER_COUNT_DOWN_TIME = "triggerTimeInSeconds"; +const char* WANT_AGENT = "wantAgent"; +const char* WANT_AGENT_PKG = "pkgName"; +const char* WANT_AGENT_ABILITY = "abilityName"; } class ReminderCommon { @@ -58,7 +74,7 @@ public: const char* propertyName, char* propertyVal, const int32_t size); static bool GetInt32(const napi_env &env, const napi_value &value, - const char* propertyName, int32_t& propertyVal); + const char* propertyName, int32_t& propertyVal, bool isNecessary); static bool GetInt64(const napi_env &env, const napi_value &value, const char* propertyName, int64_t& propertyVal); @@ -67,8 +83,20 @@ public: const char* propertyName, napi_value& propertyVal); private: - static bool CreateReminder(const napi_env &env, const napi_value &value, - const int32_t &reminderType, std::shared_ptr& reminder); + static bool CheckCalendarParams(const int32_t &year, const int32_t &month, const int32_t &day, + const int32_t &hour, const int32_t &min); + + static napi_value CreateReminderTimer( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder); + + static napi_value CreateReminderAlarm( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder); + + static napi_value CreateReminderCalendar( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder); + + static bool CreateReminder( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder); static bool GetPropertyValIfExist(const napi_env &env, const napi_value &value, const char* propertyName, napi_value& propertyVal); @@ -76,20 +104,17 @@ private: static void GenWantAgent( const napi_env &env, const napi_value &value, std::shared_ptr& reminder); - static bool GenActionButtons( - const napi_env &env, const napi_value &value, std::shared_ptr& reminder); - - static napi_value GenReminder( + static void GenMaxScreenWantAgent( const napi_env &env, const napi_value &value, std::shared_ptr& reminder); - static napi_value CreateReminderTimer( + static bool GenActionButtons( const napi_env &env, const napi_value &value, std::shared_ptr& reminder); - static napi_value CreateReminderAlarm( + static napi_value GenReminder( const napi_env &env, const napi_value &value, std::shared_ptr& reminder); - static napi_value ParseDaysOfWeek( - const napi_env &env, const napi_value &value, std::vector &daysOfWeek); + static napi_value ParseInt32Array(const napi_env &env, const napi_value &value, + const char* propertyName, std::vector &propertyVal, uint8_t maxLen); }; } // namespace OHOS } // namespace ReminderAgentNapi diff --git a/interfaces/kits/napi/ans/src/reminder/native_module.cpp b/interfaces/kits/napi/ans/src/reminder/native_module.cpp index 386a92f3c550c05f4c0cb1f733aec382b9e21ed4..f4fe3650ba080b8ce115245cd6fed1f18e68a762 100644 --- a/interfaces/kits/napi/ans/src/reminder/native_module.cpp +++ b/interfaces/kits/napi/ans/src/reminder/native_module.cpp @@ -51,12 +51,18 @@ napi_value ConstantInit(napi_env env, napi_value exports) if (napi_create_int32(env, static_cast(ReminderRequest::ReminderType::ALARM), &prop) == napi_ok) { napi_set_named_property(env, objReminderType, "REMINDER_TYPE_ALARM", prop); } + if (napi_create_int32(env, static_cast(ReminderRequest::ReminderType::CALENDAR), &prop) == napi_ok) { + napi_set_named_property(env, objReminderType, "REMINDER_TYPE_CALENDAR", prop); + } napi_value objButtonType = nullptr; napi_create_object(env, &objButtonType); if (napi_create_int32(env, static_cast(ReminderRequest::ActionButtonType::CLOSE), &prop) == napi_ok) { napi_set_named_property(env, objButtonType, "ACTION_BUTTON_TYPE_CLOSE", prop); } + if (napi_create_int32(env, static_cast(ReminderRequest::ActionButtonType::SNOOZE), &prop) == napi_ok) { + napi_set_named_property(env, objButtonType, "ACTION_BUTTON_TYPE_SNOOZE", prop); + } napi_property_descriptor exportFuncs[] = { DECLARE_NAPI_PROPERTY("ReminderType", objReminderType), diff --git a/interfaces/kits/napi/ans/src/reminder/publish.cpp b/interfaces/kits/napi/ans/src/reminder/publish.cpp index 699925f0c11b87733eb28ca3d8184e85afca0517..2f792d95909723239f1720371ae218482659c715 100644 --- a/interfaces/kits/napi/ans/src/reminder/publish.cpp +++ b/interfaces/kits/napi/ans/src/reminder/publish.cpp @@ -16,6 +16,7 @@ #include "ans_log_wrapper.h" #include "common.h" #include "reminder_request_alarm.h" +#include "reminder_request_calendar.h" #include "reminder_request_timer.h" #include "reminder/publish.h" @@ -105,8 +106,7 @@ napi_value ParseCanCelParameter(const napi_env &env, const napi_callback_info &i // argv[0]: reminder id int32_t reminderId = -1; - if (!ReminderCommon::GetInt32(env, argv[0], nullptr, reminderId)) { - ANSR_LOGW("Param id of cancels Reminder should be a number."); + if (!ReminderCommon::GetInt32(env, argv[0], nullptr, reminderId, true)) { return nullptr; } if (reminderId < 0) { @@ -279,42 +279,99 @@ napi_value CancelAllReminders(napi_env env, napi_callback_info info) } } +void ParseReminderTimer(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + napi_value value = nullptr; + ReminderRequestTimer& timer = (ReminderRequestTimer&)reminder; + napi_create_uint32(env, timer.GetInitInfo(), &value); + napi_set_named_property(env, result, TIMER_COUNT_DOWN_TIME, value); +} + +void ParseReminderAlarm(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + // hour + napi_value value = nullptr; + ReminderRequestAlarm& alarm = (ReminderRequestAlarm&)reminder; + napi_create_uint32(env, static_cast(alarm.GetHour()), &value); + napi_set_named_property(env, result, ALARM_HOUR, value); + + // minute + napi_create_uint32(env, static_cast(alarm.GetMinute()), &value); + napi_set_named_property(env, result, ALARM_MINUTE, value); + + // daysOfWeek + napi_create_array(env, &value); + napi_set_named_property(env, result, ALARM_DAYS_OF_WEEK, value); + int count = 0; + for (auto day : alarm.GetDaysOfWeek()) { + if (day) { + napi_value napiDay = nullptr; + napi_create_int32(env, day, &napiDay); + napi_set_element(env, value, count, napiDay); + count++; + } + } +} + +void ParseReminderCalendar(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + // dateTime + napi_value value = nullptr; + ReminderRequestCalendar& calender = (ReminderRequestCalendar&)reminder; + napi_value dateTime = nullptr; + napi_create_object(env, &dateTime); + napi_set_named_property(env, result, CALENDAR_DATE_TIME, dateTime); + + napi_create_uint32(env, static_cast(calender.GetYear()), &value); + napi_set_named_property(env, dateTime, CALENDAR_YEAR, value); + napi_create_uint32(env, static_cast(calender.GetMonth()), &value); + napi_set_named_property(env, dateTime, CALENDAR_MONTH, value); + napi_create_uint32(env, static_cast(calender.GetDay()), &value); + napi_set_named_property(env, dateTime, CALENDAR_DAY, value); + napi_create_uint32(env, static_cast(calender.GetHour()), &value); + napi_set_named_property(env, dateTime, CALENDAR_HOUR, value); + napi_create_uint32(env, static_cast(calender.GetMinute()), &value); + napi_set_named_property(env, dateTime, CALENDAR_MINUTE, value); + napi_create_uint32(env, static_cast(calender.GetSecond()), &value); + napi_set_named_property(env, dateTime, CALENDAR_SECOND, value); + + // repeatMonths + napi_create_array(env, &value); + napi_set_named_property(env, result, CALENDAR_REPEAT_MONTHS, value); + int count = 0; + for (auto month : calender.GetRepeatMonths()) { + napi_value napiDay = nullptr; + napi_create_int32(env, month, &napiDay); + napi_set_element(env, value, count, napiDay); + count++; + } + + // repeatDays + napi_create_array(env, &value); + napi_set_named_property(env, result, CALENDAR_REPEAT_DAYS, value); + count = 0; + for (auto day : calender.GetRepeatDays()) { + napi_value napiDay = nullptr; + napi_create_int32(env, day, &napiDay); + napi_set_element(env, value, count, napiDay); + count++; + } +} + void ParseReminder( const napi_env &env, ReminderRequest::ReminderType &type, ReminderRequest &reminder, napi_value &result) { - napi_value value = nullptr; switch (type) { case ReminderRequest::ReminderType::TIMER: { - ReminderRequestTimer& timer = (ReminderRequestTimer&)reminder; - napi_create_uint32(env, timer.GetInitInfo(), &value); - napi_set_named_property(env, result, TIMER_COUNT_DOWN_TIME, value); + ParseReminderTimer(env, reminder, result); break; } case ReminderRequest::ReminderType::ALARM: { - ANSR_LOGD("Parse alarm info"); - - // hour - ReminderRequestAlarm& alarm = (ReminderRequestAlarm&)reminder; - napi_create_uint32(env, static_cast(alarm.GetHour()), &value); - - // minute - napi_set_named_property(env, result, ALARM_HOUR, value); - napi_create_uint32(env, static_cast(alarm.GetMinute()), &value); - napi_set_named_property(env, result, ALARM_MINUTE, value); - - // daysOfWeek - napi_create_array(env, &value); - napi_set_named_property(env, result, ALARM_DAYS_OF_WEEK, value); - int count = 0; - for (auto day : alarm.GetDaysOfWeek()) { - if (day) { - napi_value napiDay = nullptr; - napi_create_int32(env, day, &napiDay); - napi_set_element(env, value, count, napiDay); - count++; - } - } - ANSR_LOGD("Parse alarm info end"); + ParseReminderAlarm(env, reminder, result); + break; + } + case ReminderRequest::ReminderType::CALENDAR: { + ParseReminderCalendar(env, reminder, result); break; } default: { @@ -334,6 +391,7 @@ void ParseActionButtons(const napi_env &env, ReminderRequest &reminder, napi_val int index = 0; for (std::map::iterator it = actionButtonsMap.begin(); it != actionButtonsMap.end(); ++it) { + // create obj napi_value actionButton = nullptr; napi_create_object(env, &actionButton); @@ -364,6 +422,20 @@ void ParseWantAgent(const napi_env &env, ReminderRequest &reminder, napi_value & napi_set_named_property(env, wantAgentInfo, WANT_AGENT_ABILITY, info); } +void ParseMaxScreenWantAgent(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + // create obj + napi_value maxScreenWantAgentInfo = nullptr; + napi_create_object(env, &maxScreenWantAgentInfo); + napi_set_named_property(env, result, MAX_SCREEN_WANT_AGENT, maxScreenWantAgentInfo); + + napi_value info = nullptr; + napi_create_string_utf8(env, (reminder.GetMaxScreenWantAgentInfo()->pkgName).c_str(), NAPI_AUTO_LENGTH, &info); + napi_set_named_property(env, maxScreenWantAgentInfo, MAX_SCREEN_WANT_AGENT_PKG, info); + napi_create_string_utf8(env, (reminder.GetMaxScreenWantAgentInfo()->abilityName).c_str(), NAPI_AUTO_LENGTH, &info); + napi_set_named_property(env, maxScreenWantAgentInfo, MAX_SCREEN_WANT_AGENT_ABILITY, info); +} + napi_value SetValidReminder(const napi_env &env, ReminderRequest &reminder, napi_value &result) { ANSR_LOGI("enter"); @@ -392,10 +464,26 @@ napi_value SetValidReminder(const napi_env &env, ReminderRequest &reminder, napi napi_create_string_utf8(env, reminder.GetExpiredContent().c_str(), NAPI_AUTO_LENGTH, &value); napi_set_named_property(env, result, EXPIRED_CONTENT, value); + // snoozeContent + napi_create_string_utf8(env, reminder.GetSnoozeContent().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, SNOOZE_CONTENT, value); + + // ringDuration + napi_create_int64(env, reminder.GetRingDuration(), &value); + napi_set_named_property(env, result, RING_DURATION, value); + + // timeInterval + napi_create_int64(env, reminder.GetTimeInterval(), &value); + napi_set_named_property(env, result, TIME_INTERVAL, value); + // notificationId napi_create_int32(env, reminder.GetNotificationId(), &value); napi_set_named_property(env, result, NOTIFICATION_ID, value); + // snoozeTimes + napi_create_int32(env, reminder.GetSnoozeTimes(), &value); + napi_set_named_property(env, result, SNOOZE_TIMES, value); + // slotType NotificationNapi::SlotType jsSlotType; NotificationNapi::Common::SlotTypeCToJS(reminder.GetSlotType(), jsSlotType); @@ -405,9 +493,11 @@ napi_value SetValidReminder(const napi_env &env, ReminderRequest &reminder, napi // wantAgent ParseWantAgent(env, reminder, result); + // maxScreenWantAgent + ParseMaxScreenWantAgent(env, reminder, result); + // actionButtons ParseActionButtons(env, reminder, result); - return NotificationNapi::Common::NapiGetBoolean(env, true); } diff --git a/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp b/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp index 7b60e4780a765f08b785bee4d5b656cb8b607c80..4bf5d4985de6999774a41888df7e9a0fa2046c83 100644 --- a/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp +++ b/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp @@ -16,6 +16,7 @@ #include "ans_log_wrapper.h" #include "common.h" #include "reminder_request_alarm.h" +#include "reminder_request_calendar.h" #include "reminder_request_timer.h" #include "reminder/reminder_common.h" @@ -30,7 +31,7 @@ napi_value ReminderCommon::GetReminderRequest( napi_valuetype valuetype = napi_undefined; NAPI_CALL(env, napi_typeof(env, value, &valuetype)); if (valuetype != napi_object) { - ANSR_LOGE("Wrong argument type. Object expected."); + ANSR_LOGW("Wrong argument type. Object expected."); return nullptr; } @@ -53,7 +54,7 @@ bool ReminderCommon::GenActionButtons( bool isArray = false; napi_is_array(env, actionButtons, &isArray); if (!isArray) { - ANSR_LOGE("Wrong argument type:%{public}s. array expected.", ACTION_BUTTON); + ANSR_LOGW("Wrong argument type:%{public}s. array expected.", ACTION_BUTTON); return false; } @@ -64,15 +65,16 @@ bool ReminderCommon::GenActionButtons( napi_get_element(env, actionButtons, i, &actionButton); NAPI_CALL(env, napi_typeof(env, actionButton, &valuetype)); if (valuetype != napi_object) { - ANSR_LOGE("Wrong element type:%{public}s. object expected.", ACTION_BUTTON); + ANSR_LOGW("Wrong element type:%{public}s. object expected.", ACTION_BUTTON); return false; } int32_t buttonType = static_cast(ReminderRequest::ActionButtonType::INVALID); if (GetStringUtf8(env, actionButton, ReminderAgentNapi::ACTION_BUTTON_TITLE, str, NotificationNapi::STR_MAX_SIZE) && - GetInt32(env, actionButton, ReminderAgentNapi::ACTION_BUTTON_TYPE, buttonType)) { - if (ReminderRequest::ActionButtonType(buttonType) != ReminderRequest::ActionButtonType::CLOSE) { + GetInt32(env, actionButton, ReminderAgentNapi::ACTION_BUTTON_TYPE, buttonType, false)) { + if (ReminderRequest::ActionButtonType(buttonType) != ReminderRequest::ActionButtonType::CLOSE && + ReminderRequest::ActionButtonType(buttonType) != ReminderRequest::ActionButtonType::SNOOZE) { ANSR_LOGW("Wrong argument type:%{public}s. buttonType not support.", ACTION_BUTTON); return false; } @@ -105,9 +107,32 @@ void ReminderCommon::GenWantAgent( } } -bool ReminderCommon::CreateReminder(const napi_env &env, const napi_value &value, - const int32_t &reminderType, std::shared_ptr& reminder) +void ReminderCommon::GenMaxScreenWantAgent( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + char str[NotificationNapi::STR_MAX_SIZE] = {0}; + napi_value maxScreenWantAgent = nullptr; + if (GetObject(env, value, ReminderAgentNapi::MAX_SCREEN_WANT_AGENT, maxScreenWantAgent)) { + std::shared_ptr maxScreenWantAgentInfo( + new ReminderRequest::MaxScreenAgentInfo()); + if (GetStringUtf8(env, maxScreenWantAgent, + ReminderAgentNapi::MAX_SCREEN_WANT_AGENT_PKG, str, NotificationNapi::STR_MAX_SIZE)) { + maxScreenWantAgentInfo->pkgName = str; + } + if (GetStringUtf8(env, maxScreenWantAgent, + ReminderAgentNapi::MAX_SCREEN_WANT_AGENT_ABILITY, str, NotificationNapi::STR_MAX_SIZE)) { + maxScreenWantAgentInfo->abilityName = str; + } + reminder->SetMaxScreenWantAgentInfo(maxScreenWantAgentInfo); + } +} +bool ReminderCommon::CreateReminder( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) { + napi_value result = nullptr; + napi_get_named_property(env, value, ReminderAgentNapi::REMINDER_TYPE, &result); + int32_t reminderType = -1; + napi_get_value_int32(env, result, &reminderType); switch (ReminderRequest::ReminderType(reminderType)) { case ReminderRequest::ReminderType::TIMER: CreateReminderTimer(env, value, reminder); @@ -115,8 +140,11 @@ bool ReminderCommon::CreateReminder(const napi_env &env, const napi_value &value case ReminderRequest::ReminderType::ALARM: CreateReminderAlarm(env, value, reminder); break; + case ReminderRequest::ReminderType::CALENDAR: + CreateReminderCalendar(env, value, reminder); + break; default: - ANSR_LOGW("Reminder type is not support."); + ANSR_LOGW("Reminder type is not support. (type:%{public}d)", reminderType); break; } if (reminder == nullptr) { @@ -133,16 +161,12 @@ napi_value ReminderCommon::GenReminder( bool hasProperty = false; NAPI_CALL(env, napi_has_named_property(env, value, ReminderAgentNapi::REMINDER_TYPE, &hasProperty)); if (!hasProperty) { - ANSR_LOGE("Property %{public}s expected.", ReminderAgentNapi::REMINDER_TYPE); + ANSR_LOGW("Property %{public}s expected.", ReminderAgentNapi::REMINDER_TYPE); return nullptr; } - napi_value result = nullptr; - napi_get_named_property(env, value, ReminderAgentNapi::REMINDER_TYPE, &result); - int32_t propertyVal = -1; - napi_get_value_int32(env, result, &propertyVal); // createReminder - if (!CreateReminder(env, value, propertyVal, reminder)) { + if (!CreateReminder(env, value, reminder)) { return nullptr; } char str[NotificationNapi::STR_MAX_SIZE] = {0}; @@ -162,14 +186,51 @@ napi_value ReminderCommon::GenReminder( reminder->SetExpiredContent(str); } + // snoozeContent + if (GetStringUtf8(env, value, ReminderAgentNapi::SNOOZE_CONTENT, str, NotificationNapi::STR_MAX_SIZE)) { + reminder->SetSnoozeContent(str); + } + + // ringDuration + int64_t propVal = 0; + if (GetInt64(env, value, ReminderAgentNapi::RING_DURATION, propVal)) { + if (propVal < 0) { + reminder->SetRingDuration(0); + } else { + uint64_t ringDuration = static_cast(propVal); + reminder->SetRingDuration(ringDuration); + } + } + + // timeInterval + if (GetInt64(env, value, ReminderAgentNapi::TIME_INTERVAL, propVal)) { + if (propVal < 0) { + reminder->SetTimeInterval(0); + } else { + uint64_t timeInterval = static_cast(propVal); + reminder->SetTimeInterval(timeInterval); + } + } + // notificationId - if (GetInt32(env, value, ReminderAgentNapi::NOTIFICATION_ID, propertyVal)) { + int32_t propertyVal = 0; + if (GetInt32(env, value, ReminderAgentNapi::NOTIFICATION_ID, propertyVal, false)) { reminder->SetNotificationId(propertyVal); } + // snoozeTimes + if (GetInt32(env, value, ReminderAgentNapi::SNOOZE_TIMES, propertyVal, false)) { + if (propertyVal < 0) { + reminder->SetSnoozeTimes(0); + } else { + uint8_t snoozeTimes = propertyVal > UINT8_MAX ? UINT8_MAX : propertyVal; + reminder->SetSnoozeTimes(static_cast(snoozeTimes)); + } + } + // slotType int32_t slotType = 0; - if (GetInt32(env, value, ReminderAgentNapi::SLOT_TYPE, slotType)) { + if (GetInt32(env, value, ReminderAgentNapi::SLOT_TYPE, slotType, false)) { enum NotificationConstant::SlotType actureType = NotificationConstant::SlotType::OTHER; if (!NotificationNapi::Common::SlotTypeJSToC(NotificationNapi::SlotType(slotType), actureType)) { ANSR_LOGW("slot type not support."); @@ -181,6 +242,9 @@ napi_value ReminderCommon::GenReminder( // wantAgent GenWantAgent(env, value, reminder); + // maxScreenWantAgent + GenMaxScreenWantAgent(env, value, reminder); + // actionButtons if (!GenActionButtons(env, value, reminder)) { return nullptr; @@ -201,7 +265,7 @@ bool ReminderCommon::GetStringUtf8(const napi_env &env, const napi_value &value, napi_get_named_property(env, value, propertyName, &result); NAPI_CALL(env, napi_typeof(env, result, &valuetype)); if (valuetype != napi_string) { - ANSR_LOGE("Wrong argument type:%{public}s. string expected.", propertyName); + ANSR_LOGW("Wrong argument type:%{public}s. string expected.", propertyName); return false; } NAPI_CALL(env, napi_get_value_string_utf8(env, result, propertyVal, size - 1, &strLen)); @@ -210,10 +274,13 @@ bool ReminderCommon::GetStringUtf8(const napi_env &env, const napi_value &value, } bool ReminderCommon::GetInt32(const napi_env &env, const napi_value &value, - const char* propertyName, int32_t& propertyVal) + const char* propertyName, int32_t& propertyVal, bool isNecessary) { napi_value result = nullptr; if (!GetPropertyValIfExist(env, value, propertyName, result)) { + if (isNecessary) { + ANSR_LOGW("Correct property %{public}s expected.", propertyName); + } return false; } napi_get_value_int32(env, result, &propertyVal); @@ -270,7 +337,7 @@ bool ReminderCommon::GetObject(const napi_env &env, const napi_value &value, napi_get_named_property(env, value, propertyName, &propertyVal); NAPI_CALL(env, napi_typeof(env, propertyVal, &valuetype)); if (valuetype != napi_object) { - ANSR_LOGE("Wrong argument type:%{public}s. object expected.", propertyName); + ANSR_LOGW("Wrong argument type:%{public}s. object expected.", propertyName); return false; } return true; @@ -281,14 +348,13 @@ napi_value ReminderCommon::CreateReminderTimer( { int64_t propertyCountDownTime = 0; if (!GetInt64(env, value, ReminderAgentNapi::TIMER_COUNT_DOWN_TIME, propertyCountDownTime)) { - ANSR_LOGE("Correct property %{public}s expected.", ReminderAgentNapi::TIMER_COUNT_DOWN_TIME); + ANSR_LOGW("Correct property %{public}s expected.", ReminderAgentNapi::TIMER_COUNT_DOWN_TIME); return nullptr; } - if (propertyCountDownTime <= 0 || - propertyCountDownTime > static_cast((UINT64_MAX / ReminderRequest::MILLI_SECONDS))) { - ANSR_LOGE("Property %{public}s must between (0, %{public}llu).", - ReminderAgentNapi::ALARM_MINUTE, (unsigned long long)(UINT64_MAX / ReminderRequest::MILLI_SECONDS)); + if (propertyCountDownTime <= 0) { + ANSR_LOGW("Create countDown reminder fail: designated %{public}s should be set larger than 0.", + ReminderAgentNapi::TIMER_COUNT_DOWN_TIME); return nullptr; } @@ -301,54 +367,128 @@ napi_value ReminderCommon::CreateReminderAlarm( { // hour int32_t propertyHourVal = 0; - if (!GetInt32(env, value, ReminderAgentNapi::ALARM_HOUR, propertyHourVal)) { - ANSR_LOGE("Correct property %{public}s expected.", ReminderAgentNapi::ALARM_HOUR); + if (!GetInt32(env, value, ReminderAgentNapi::ALARM_HOUR, propertyHourVal, true)) { return nullptr; } // minute int32_t propertyMinuteVal = 0; - if (!GetInt32(env, value, ReminderAgentNapi::ALARM_MINUTE, propertyMinuteVal)) { - ANSR_LOGE("Correct property %{public}s expected.", ReminderAgentNapi::ALARM_MINUTE); + if (!GetInt32(env, value, ReminderAgentNapi::ALARM_MINUTE, propertyMinuteVal, true)) { return nullptr; } if (propertyHourVal < 0 || propertyHourVal > 23) { - ANSR_LOGE("Property %{public}s must between [0, 23].", ReminderAgentNapi::ALARM_HOUR); + ANSR_LOGW("Create alarm reminder fail: designated %{public}s must between [0, 23].", + ReminderAgentNapi::ALARM_HOUR); return nullptr; } if (propertyMinuteVal < 0 || propertyMinuteVal > 59) { - ANSR_LOGE("Property %{public}s must between [0, 59].", ReminderAgentNapi::ALARM_MINUTE); + ANSR_LOGW("Create alarm reminder fail: designated %{public}s must between [0, 59].", + ReminderAgentNapi::ALARM_MINUTE); return nullptr; } // daysOfWeek std::vector daysOfWeek; - ParseDaysOfWeek(env, value, daysOfWeek); + uint8_t maxDaysOfWeek = 7; + if (ParseInt32Array(env, value, ReminderAgentNapi::ALARM_DAYS_OF_WEEK, daysOfWeek, maxDaysOfWeek) == nullptr) { + return nullptr; + } reminder = std::make_shared( static_cast(propertyHourVal), static_cast(propertyMinuteVal), daysOfWeek); return NotificationNapi::Common::NapiGetNull(env); } -napi_value ReminderCommon::ParseDaysOfWeek( - const napi_env &env, const napi_value &value, std::vector &daysOfWeek) +napi_value ReminderCommon::CreateReminderCalendar( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + napi_value dateTimeObj = nullptr; + if (!GetObject(env, value, ReminderAgentNapi::CALENDAR_DATE_TIME, dateTimeObj)) { + ANSR_LOGW("Create calender reminder fail: dateTime must be setted."); + return nullptr; + } + + // year month day hour minute second + int32_t propertyYearVal = 0; + int32_t propertyMonthVal = 0; + int32_t propertyDayVal = 0; + int32_t propertyHourVal = 0; + int32_t propertyMinteVal = 0; + if (!GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_YEAR, propertyYearVal, true) + || !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_MONTH, propertyMonthVal, true) + || !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_DAY, propertyDayVal, true) + || !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_HOUR, propertyHourVal, true) + || !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_MINUTE, propertyMinteVal, true)) { + return nullptr; + } + if (!CheckCalendarParams(propertyYearVal, propertyMonthVal, propertyDayVal, + propertyHourVal, propertyMinteVal)) { + return nullptr; + } + + // repeatMonth + std::vector repeatMonths; + if (ParseInt32Array(env, value, ReminderAgentNapi::CALENDAR_REPEAT_MONTHS, repeatMonths, + ReminderRequestCalendar::MAX_MONTHS_OF_YEAR) == nullptr) { + return nullptr; + } + + // repeatDay + std::vector repeatDays; + if (ParseInt32Array(env, value, ReminderAgentNapi::CALENDAR_REPEAT_DAYS, repeatDays, + ReminderRequestCalendar::MAX_DAYS_OF_MONTH) == nullptr) { + return nullptr; + } + + tm dateTime; + dateTime.tm_year = ReminderRequest::GetCTime(ReminderRequest::TimeTransferType::YEAR, propertyYearVal); + dateTime.tm_mon = ReminderRequest::GetCTime(ReminderRequest::TimeTransferType::MONTH, propertyMonthVal); + dateTime.tm_mday = propertyDayVal; + dateTime.tm_hour = propertyHourVal; + dateTime.tm_min = propertyMinteVal; + dateTime.tm_sec = 0; + reminder = std::make_shared(dateTime, repeatMonths, repeatDays); + return NotificationNapi::Common::NapiGetNull(env); +} + +bool ReminderCommon::CheckCalendarParams(const int32_t &year, const int32_t &month, const int32_t &day, + const int32_t &hour, const int32_t &min) +{ + if (year < 0 || year > UINT16_MAX) { + ANSR_LOGW("Create calender reminder fail: designated %{public}s must between [0, %{public}u]", + ReminderAgentNapi::CALENDAR_YEAR, UINT16_MAX); + return false; + } + if (month < 1 || month > ReminderRequestCalendar::MAX_MONTHS_OF_YEAR) { + ANSR_LOGW("Create calender reminder fail: designated %{public}s must between [1, %{public}u]", + ReminderAgentNapi::CALENDAR_MONTH, ReminderRequestCalendar::MAX_MONTHS_OF_YEAR); + return false; + } + if (day < 1 || day > ReminderRequestCalendar::MAX_DAYS_OF_MONTH) { + ANSR_LOGW("Create calender reminder fail: designated %{public}s must between [1, %{public}u]", + ReminderAgentNapi::CALENDAR_DAY, ReminderRequestCalendar::MAX_DAYS_OF_MONTH); + return false; + } + return true; +} + +napi_value ReminderCommon::ParseInt32Array(const napi_env &env, const napi_value &value, + const char* propertyName, std::vector &propertyVal, uint8_t maxLen) { napi_value result = nullptr; - if (!GetObject(env, value, ReminderAgentNapi::ALARM_DAYS_OF_WEEK, result)) { + if (!GetObject(env, value, propertyName, result)) { return NotificationNapi::Common::NapiGetNull(env); } if (result != nullptr) { bool isArray = false; napi_is_array(env, result, &isArray); if (!isArray) { - ANSR_LOGE("Property %{public}s is expected to be an array.", ReminderAgentNapi::ALARM_DAYS_OF_WEEK); + ANSR_LOGW("Property %{public}s is expected to be an array.", propertyName); return nullptr; } uint32_t length = 0; napi_get_array_length(env, result, &length); - uint8_t maxDaysOfWeek = 7; - if (length > maxDaysOfWeek) { - ANSR_LOGE( - "The max length of array of %{public}s is %{public}d.", ALARM_DAYS_OF_WEEK, maxDaysOfWeek); + if (length > maxLen) { + ANSR_LOGW("The max length of array of %{public}s is %{public}d.", propertyName, maxLen); return nullptr; } napi_valuetype valuetype = napi_undefined; @@ -358,20 +498,18 @@ napi_value ReminderCommon::ParseDaysOfWeek( napi_get_element(env, result, i, &repeatDayVal); NAPI_CALL(env, napi_typeof(env, repeatDayVal, &valuetype)); if (valuetype != napi_number) { - ANSR_LOGE("%{public}s's element is expected to be number.", - ReminderAgentNapi::ALARM_DAYS_OF_WEEK); + ANSR_LOGW("%{public}s's element is expected to be number.", propertyName); return nullptr; } napi_get_value_int32(env, repeatDayVal, &propertyDayVal); - if (propertyDayVal < 1 || propertyDayVal > maxDaysOfWeek) { - ANSR_LOGE("%{public}s's element must between [1, %{public}d].", - ReminderAgentNapi::ALARM_DAYS_OF_WEEK, maxDaysOfWeek); + if (propertyDayVal < 1 || propertyDayVal > maxLen) { + ANSR_LOGW("%{public}s's element must between [1, %{public}d].", propertyName, maxLen); return nullptr; } - daysOfWeek.push_back(static_cast(propertyDayVal)); + propertyVal.push_back(static_cast(propertyDayVal)); } } return NotificationNapi::Common::NapiGetNull(env); } } -} \ No newline at end of file +} diff --git a/services/ans/BUILD.gn b/services/ans/BUILD.gn index c8d57053535446bfc35b43ecb32511796a746203..12c62d3079d00a2f0828f1a3df7197bd455b9da4 100644 --- a/services/ans/BUILD.gn +++ b/services/ans/BUILD.gn @@ -71,8 +71,10 @@ ohos_shared_library("libans") { external_deps = [ "ability_runtime:abilitykit_native", + "ability_runtime:app_manager", "distributeddatamgr:distributeddata_inner", "multimedia_image_standard:image_native", + "multimedia_media_standard:media_client", "os_account_standard:os_account_innerkits", "time_native:time_service", ] diff --git a/services/ans/include/advanced_notification_service.h b/services/ans/include/advanced_notification_service.h index f7029a8c41010d48d09d29d623632b563abb6531..b4b7abeb0317af9a16f61b97f224e119792921d5 100644 --- a/services/ans/include/advanced_notification_service.h +++ b/services/ans/include/advanced_notification_service.h @@ -131,6 +131,8 @@ public: // Distributed KvStore void OnDistributedKvStoreDeathRecipient(); + ErrCode CancelPreparedNotification( + int notificationId, const std::string &label, const sptr &bundleOption); ErrCode PrepareNotificationInfo( const sptr &request, sptr &bundleOption); ErrCode PublishPreparedNotification( diff --git a/services/ans/include/reminder_data_manager.h b/services/ans/include/reminder_data_manager.h index 8990973c2356a39ecfa16acbcb66513f84a2d57c..531060b79d807b4bfa89e0afdbcb60decb46c0bd 100644 --- a/services/ans/include/reminder_data_manager.h +++ b/services/ans/include/reminder_data_manager.h @@ -20,6 +20,7 @@ #include #include "advanced_notification_service.h" +#include "player.h" #include "reminder_request.h" #include "reminder_timer_info.h" @@ -78,6 +79,13 @@ public: void GetValidReminders( const sptr bundleOption, std::vector> &reminders); + /** + * @brief Triggered when third party application died. + * + * @param bundleOption Indicates the bundleOption of third party application. + */ + void OnProcessDiedLocked(const sptr bundleOption); + /** * Publishs a scheduled reminder. * @@ -105,18 +113,60 @@ public: * * @param isSysTimeChanged Indicates it is triggered as dateTime changed by user or not. */ - void ShowReminder(bool isSysTimeChanged); + void ShowActiveReminder(); + + /** + * @brief Snooze the reminder by manual. + * 1) Snooze the trigger time to the next. + * 2) Update the notification(Update notification lable/content...; Stop audio player and vibrator) + * 3) Show the notification dialog in the SystemUI + * 4) Start a new reminder, which is recent one now. + * + * @param want Which contains the given reminder. + */ + void SnoozeReminder(const OHOS::EventFwk::Want &want); + + /** + * @brief Terminate the alerting reminder. + * + * 1. Stop sound and vibrate. + * 2. Stop the alerting timer. + * 3. Update the reminder state. + * 4. Update the display content of the notification. + * + * @param want Which contains the given reminder. + */ + void TerminateAlerting(const OHOS::EventFwk::Want &want); static const uint8_t TIME_ZONE_CHANGE; static const uint8_t DATE_TIME_CHANGE; private: + enum class TimerType : uint8_t { + TRIGGER_TIMER, + ALERTING_TIMER + }; + + /** + * Add default slot to the reminder if no slot set by user. + * + * @param reminder Indicates the reminder. + */ + void AddDefaultSlotIfNeeded(sptr &reminder); + + /** + * Add reminder to showed reminder vector. + * + * @param reminder Indicates the showed reminder. + */ + void AddToShowedReminders(const sptr &reminder); + /** * Cancels the notification relative to the reminder. * * @param reminder Indicates the reminder. */ - void CancelNotification(sptr &reminder) const; + void CancelNotification(const sptr &reminder) const; /** * Check whether the number limit of reminders if exceeded. @@ -125,15 +175,17 @@ private: * @return true if number limit is exceeded. */ bool CheckReminderLimitExceededLocked(const std::string &bundleName) const; - - void CloseReminder(const int32_t &reminderId, bool cancelNotification); + void CloseReminder(const sptr &reminder, bool cancelNotification); /** * Create a information for timer, such as timer type, repeat policy, interval and want agent. * + * @param type Indicates the timer type. * @return pointer of ReminderTimerInfo. */ - std::shared_ptr CreateTimerInfo() const; + std::shared_ptr CreateTimerInfo(TimerType type) const; + + std::string GetSoundUri(const sptr &reminder); /** * Find the reminder from reminderVector_ by reminder id. @@ -159,7 +211,7 @@ private: * @param reminderId Indicates the reminder id. * @return pointer of NotificationBundleOption or nullptr. */ - sptr FindNotificationBundleOption(const int32_t &reminderId); + sptr FindNotificationBundleOption(const int32_t &reminderId) const; /** * Obtains the recent reminder which is not expired from reminder vector. @@ -197,6 +249,8 @@ private: */ void HandleSameNotificationIdShowing(const sptr reminder); + bool HandleSysTimeChange(const sptr reminder) const; + /** * Judge the two reminders is belong to the same application or not. * @@ -208,6 +262,18 @@ private: bool IsBelongToSameApp( const sptr reminder, const std::string otherPkgName, const int otherUserId); + void PlaySoundAndVibrationLocked(const sptr &reminder); + void PlaySoundAndVibration(const sptr &reminder); + void StopSoundAndVibrationLocked(const sptr &reminder); + void StopSoundAndVibration(const sptr &reminder); + + /** + * Remove from showed reminder vector. + * + * @param reminder Indicates the reminder need to remove. + */ + void RemoveFromShowedReminders(const sptr &reminder); + /** * @brief Refresh the all reminders due to date/time or timeZone change by user. * @@ -227,12 +293,30 @@ private: /** * Resets timer status. - * 1. Sets timerId_ with 0. - * 2. Sets activeReminderId_ with -1. + * 1. Sets timerId_ or timerIdAlerting_ with 0. + * 2. Sets activeReminderId_ or alertingReminderId with -1. + * + * @param type Indicates the timer type. + */ + void ResetStates(TimerType type); + + void SetActiveReminder(const sptr &reminder); + void SetAlertingReminder(const sptr &reminder); + void ShowActiveReminderExtendLocked(sptr &reminder); + + /** + * @brief Show the reminder on SystemUI. + * + * @param reminder Indicates the reminder to show. + * @param isNeedToPlaySound Indicates whether need to play sound. + * @param isNeedToStartNext Indicates whether need to start next reminder. + * @param isSysTimeChanged Indicates whether it is triggerred as system time changed by user. + * @param needScheduleTimeout Indicates whether need to control the ring duration. */ - void ResetStates(); + void ShowReminder(const sptr &reminder, const bool &isNeedToPlaySound, + const bool &isNeedToStartNext, const bool &isSysTimeChanged, const bool &needScheduleTimeout); - void ShowDesignatedReminderLocked(sptr &reminder, bool isSysTimeChanged); + void SnoozeReminderImpl(sptr &reminder); /** * Starts the recent reminder timing. @@ -243,18 +327,42 @@ private: * Starts timing actually. * * @param reminderRequest Indicates the reminder. + * @param type Indicates the timer type. */ - void StartTimerLocked(sptr &reminderRequest); + void StartTimerLocked(const sptr &reminderRequest, TimerType type); + void StartTimer(const sptr &reminderRequest, TimerType type); /** - * Stops timing. + * @brief Stop the alerting timer and update reminder information. + * + * 1. Stop sound and vibrate. + * 2. Stop the alerting timer. + * + * @param reminder Indicates the target reminder. */ - void StopTimer(); + void StopAlertingReminder(const sptr &reminder); /** * Stops timing. + * + * @param type Indicates the timer type. + */ + void StopTimer(TimerType type); + void StopTimerLocked(TimerType type); + + /** + * @brief Terminate the alerting reminder. + * + * 1. Stop sound and vibrate. + * 2. Stop the alerting timer. + * 3. Update the reminder state. + * 4. Update the display content of the notification. + * + * @param reminder Indicates the reminder. + * @param reason Indicates the description information. */ - void StopTimerLocked(); + void TerminateAlerting(const sptr &reminder, const std::string &reason); + void TerminateAlerting(const uint16_t waitInMilli, const sptr &reminder); /** * @brief Assign unique reminder id and save reminder in memory. @@ -265,6 +373,8 @@ private: void UpdateAndSaveReminderLocked( const sptr &reminder, const sptr &bundleOption); + void UpdateNotification(const sptr &reminder); + static bool cmp(sptr &reminderRequest, sptr &other); /** @@ -276,6 +386,8 @@ private: * Used for multi-thread syncronise. */ static std::mutex MUTEX; + static std::mutex SHOW_MUTEX; + static std::mutex ALERT_MUTEX; /** * Max number of reminders limit for the whole system. @@ -287,27 +399,44 @@ private: */ static const int16_t MAX_NUM_REMINDER_LIMIT_APP; - static const uint16_t SAME_TIME_DISTINGUISH_MILLISECONDS; - /** * Vector used to record all the reminders in system. */ std::vector> reminderVector_; + /** + * Vector used to record all the reminders which has been shown on panel. + */ + std::vector> shownReminderVector_; + /** * Map used to record all the bundle information of the reminders in system. */ std::map> notificationBundleOptionMap_; /** - * Indicates the id of the timer that has called StartTimerLocked. + * This timer is used to control the triggerTime of next reminder. */ uint64_t timerId_ {0}; + /** + * This timer is used to control the ringDuration of the alerting reminder. + */ + uint64_t timerIdAlerting_ {0}; + /** * Indicates the active reminder that timing is taking effect. */ - int32_t activeReminderId_ {-1}; + int32_t activeReminderId_ = -1; + sptr activeReminder_ = nullptr; + + /** + * Indicates the reminder which is playing sound or vibration. + */ + int32_t alertingReminderId_ = -1; + sptr alertingReminder_ = nullptr; + + std::shared_ptr soundPlayer_ = nullptr; /** * Indicates the total count of reminders in system. @@ -317,5 +446,4 @@ private: }; } // namespace OHOS } // namespace Nofitifcation - #endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_DATA_MANAGER_H \ No newline at end of file diff --git a/services/ans/include/reminder_event_manager.h b/services/ans/include/reminder_event_manager.h index 25a20792aa8ed0dd12ffa4ed1a94c681b77cef66..bfc72148d4603a04b80715a537dec6c00f2db6d2 100644 --- a/services/ans/include/reminder_event_manager.h +++ b/services/ans/include/reminder_event_manager.h @@ -40,6 +40,10 @@ public: virtual void OnReceiveEvent(const EventFwk::CommonEventData &data); private: + sptr GetBundleOption(const OHOS::EventFwk::Want &want) const; + void HandlePackageRemove(OHOS::EventFwk::Want &want) const; + void HandleProcessDied(OHOS::EventFwk::Want &want) const; + int32_t GetUid(const int userId, const std::string bundleName) const; std::shared_ptr reminderDataManager_; }; }; diff --git a/services/ans/include/reminder_timer_info.h b/services/ans/include/reminder_timer_info.h index 0bc1e891e0c8fde42d73b3881c1f73e14738fd29..043492369a35df85af4f6eea2080b27cf5d44a24 100644 --- a/services/ans/include/reminder_timer_info.h +++ b/services/ans/include/reminder_timer_info.h @@ -31,6 +31,10 @@ public: ReminderTimerInfo(ReminderTimerInfo &other) = delete; ReminderTimerInfo& operator = (const ReminderTimerInfo &other) = delete; + inline void SetAction(const std::string &action) { + action_ = action; + } + /** * When timing is up, this function will execute as call back. */ @@ -56,10 +60,8 @@ public: */ void SetWantAgent(std::shared_ptr wantAgent) override; - /** - * Publish common event. - */ - bool PublishCommonEvent(const std::string &action) const; +private: + std::string action_; }; } // namespace OHOS } // namespace Notification diff --git a/services/ans/src/advanced_notification_service.cpp b/services/ans/src/advanced_notification_service.cpp index 484f975bcc06bbe50399495425d8aae2334ec599..61f7b0daa006893c0b7c5d08006d13f96593d62c 100644 --- a/services/ans/src/advanced_notification_service.cpp +++ b/services/ans/src/advanced_notification_service.cpp @@ -292,6 +292,33 @@ ErrCode AdvancedNotificationService::AssignToNotificationList(const std::shared_ return result; } +ErrCode AdvancedNotificationService::CancelPreparedNotification( + int notificationId, const std::string &label, const sptr &bundleOption) +{ + if (bundleOption == nullptr) { + return ERR_ANS_INVALID_BUNDLE; + } + ErrCode result = ERR_OK; + handler_->PostSyncTask(std::bind([&]() { + sptr notification = nullptr; + result = RemoveFromNotificationList(bundleOption, label, notificationId, notification, true); + if (result != ERR_OK) { + return; + } + + if (notification != nullptr) { + int reason = NotificationConstant::APP_CANCEL_REASON_DELETE; + UpdateRecentNotification(notification, true, reason); + sptr sortingMap = GenerateSortingMap(); + NotificationSubscriberManager::GetInstance()->NotifyCanceled(notification, sortingMap, reason); +#ifdef DISTRIBUTED_NOTIFICATION_SUPPORTED + DoDistributedDelete("", notification); +#endif + } + })); + return result; +} + ErrCode AdvancedNotificationService::PrepareNotificationInfo( const sptr &request, sptr &bundleOption) { @@ -454,29 +481,7 @@ ErrCode AdvancedNotificationService::Cancel(int notificationId, const std::strin { ANS_LOGD("%{public}s", __FUNCTION__); sptr bundleOption = GenerateBundleOption(); - if (bundleOption == nullptr) { - return ERR_ANS_INVALID_BUNDLE; - } - - ErrCode result = ERR_OK; - handler_->PostSyncTask(std::bind([&]() { - sptr notification = nullptr; - result = RemoveFromNotificationList(bundleOption, label, notificationId, notification, true); - if (result != ERR_OK) { - return; - } - - if (notification != nullptr) { - int reason = NotificationConstant::APP_CANCEL_REASON_DELETE; - UpdateRecentNotification(notification, true, reason); - sptr sortingMap = GenerateSortingMap(); - NotificationSubscriberManager::GetInstance()->NotifyCanceled(notification, sortingMap, reason); -#ifdef DISTRIBUTED_NOTIFICATION_SUPPORTED - DoDistributedDelete("", notification); -#endif - } - })); - return result; + return CancelPreparedNotification(notificationId, label, bundleOption); } ErrCode AdvancedNotificationService::CancelAll() @@ -2825,4 +2830,4 @@ void AdvancedNotificationService::TriggerRemoveWantAgent(const sptr ReminderDataManager::REMINDER_DATA_MANAGER = nullptr; std::mutex ReminderDataManager::MUTEX; +std::mutex ReminderDataManager::SHOW_MUTEX; +std::mutex ReminderDataManager::ALERT_MUTEX; void ReminderDataManager::PublishReminder(sptr &reminder, sptr &bundleOption) @@ -49,9 +52,13 @@ void ReminderDataManager::CancelReminder( ANSR_LOGW("Cancel reminder, not find the reminder"); return; } - if (activeReminderId_ != -1 && activeReminderId_ == reminderId) { - ANSR_LOGD("Cancel active reminder, id=%{public}d", activeReminderId_); - StopTimerLocked(); + if (activeReminderId_ == reminderId) { + ANSR_LOGD("Cancel active reminder, id=%{public}d", reminderId); + StopTimerLocked(TimerType::TRIGGER_TIMER); + } + if (alertingReminderId_ == reminderId) { + StopTimerLocked(TimerType::ALERTING_TIMER); + StopSoundAndVibrationLocked(reminder); } int32_t id = reminderId; RemoveReminderLocked(id); @@ -59,7 +66,7 @@ void ReminderDataManager::CancelReminder( StartRecentReminder(); } -void ReminderDataManager::CancelNotification(sptr &reminder) const +void ReminderDataManager::CancelNotification(const sptr &reminder) const { if (!(reminder->IsShowing())) { ANSR_LOGD("No need to cancel notification"); @@ -75,7 +82,9 @@ void ReminderDataManager::CancelNotification(sptr &reminder) co ANSR_LOGE("Cancel notification fail"); return; } - advancedNotificationService_->Cancel(notification->GetNotificationId(), ReminderRequest::NOTIFICATION_LABEL); + sptr bundleOption = FindNotificationBundleOption(reminder->GetReminderId()); + advancedNotificationService_->CancelPreparedNotification( + notification->GetNotificationId(), ReminderRequest::NOTIFICATION_LABEL, bundleOption); } bool ReminderDataManager::CheckReminderLimitExceededLocked(const std::string &bundleName) const @@ -113,10 +122,10 @@ void ReminderDataManager::CancelAllReminders(const sptrsecond->GetBundleName() == bundleOption->GetBundleName()) { - StopTimer(); + StopTimer(TimerType::TRIGGER_TIMER); } } for (auto vit = reminderVector_.begin(); vit != reminderVector_.end();) { @@ -124,15 +133,19 @@ void ReminderDataManager::CancelAllReminders(const sptrsecond->GetBundleName() == bundleOption->GetBundleName()) { - CancelNotification(*vit); - ANSR_LOGD("Containers(vector/map) remove. reminderId=%{public}d", reminderId); - vit = reminderVector_.erase(vit); - notificationBundleOptionMap_.erase(mit); - totalCount_--; - continue; + ++vit; + continue; + } + if (mit->second->GetBundleName() == bundleOption->GetBundleName()) { + if ((*vit)->IsAlerting()) { + StopAlertingReminder(*vit); } + CancelNotification(*vit); + ANSR_LOGD("Containers(vector/map) remove. reminderId=%{public}d", reminderId); + vit = reminderVector_.erase(vit); + notificationBundleOptionMap_.erase(mit); + totalCount_--; + continue; } ++vit; } @@ -160,13 +173,88 @@ void ReminderDataManager::GetValidReminders( } } -std::shared_ptr ReminderDataManager::CreateTimerInfo() const +void ReminderDataManager::AddToShowedReminders(const sptr &reminder) +{ + std::lock_guard lock(ReminderDataManager::SHOW_MUTEX); + for (auto it = shownReminderVector_.begin(); it != shownReminderVector_.end(); ++it) { + if (reminder->GetReminderId() == (*it)->GetReminderId()) { + ANSR_LOGD("Showed reminder is already exist"); + return; + } + } + ANSR_LOGD("Containers(shownVector) add. reminderId=%{public}d", reminder->GetReminderId()); + shownReminderVector_.push_back(reminder); +} + +void ReminderDataManager::OnProcessDiedLocked(const sptr bundleOption) +{ + std::string bundleName = bundleOption->GetBundleName(); + int32_t uid = bundleOption->GetUid(); + ANSR_LOGI("OnProcessDiedLocked, bundleName=%{public}s, uid=%{public}d", bundleName.c_str(), uid); + std::lock_guard lock(ReminderDataManager::SHOW_MUTEX); + for (auto it = shownReminderVector_.begin(); it != shownReminderVector_.end(); ++it) { + int32_t reminderId = (*it)->GetReminderId(); + auto mit = notificationBundleOptionMap_.find(reminderId); + if (mit == notificationBundleOptionMap_.end()) { + ANSR_LOGE("Get bundle option occur error, reminderId=%{public}d", reminderId); + continue; + } + if (mit->second->GetBundleName() != bundleName || mit->second->GetUid() != uid) { + continue; + } + if ((*it)->IsAlerting()) { + TerminateAlerting((*it), "onProcessDied"); + } else { + CancelNotification(*it); + (*it)->OnClose(false); + ANSR_LOGD("Containers(shownVector) remove. reminderId=%{public}d", reminderId); + shownReminderVector_.erase(it); + --it; + } + } +} + +std::shared_ptr ReminderDataManager::CreateTimerInfo(TimerType type) const { auto sharedTimerInfo = std::make_shared(); sharedTimerInfo->SetType(sharedTimerInfo->TIMER_TYPE_WAKEUP|sharedTimerInfo->TIMER_TYPE_EXACT); sharedTimerInfo->SetRepeat(false); sharedTimerInfo->SetInterval(0); - sharedTimerInfo->SetWantAgent(nullptr); + + int requestCode = 10; + std::vector flags; + flags.push_back(WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); + auto want = std::make_shared(); + + switch (type) { + case (TimerType::TRIGGER_TIMER): { + want->SetAction(ReminderRequest::REMINDER_EVENT_ALARM_ALERT); + break; + } + case (TimerType::ALERTING_TIMER): { + if (alertingReminderId_ == -1) { + ANSR_LOGE("Create alerting time out timer Illegal."); + return sharedTimerInfo; + } + want->SetAction(ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT); + want->SetParam(ReminderRequest::PARAM_REMINDER_ID, alertingReminderId_); + break; + } + default: + ANSR_LOGE("TimerType not support"); + break; + } + std::vector> wants; + wants.push_back(want); + WantAgent::WantAgentInfo wantAgentInfo( + requestCode, + WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT, + flags, + wants, + nullptr + ); + std::shared_ptr wantAgent = WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo); + sharedTimerInfo->SetWantAgent(wantAgent); return sharedTimerInfo; } @@ -202,7 +290,7 @@ sptr ReminderDataManager::FindReminderRequestLocked( return reminder; } -sptr ReminderDataManager::FindNotificationBundleOption(const int32_t &reminderId) +sptr ReminderDataManager::FindNotificationBundleOption(const int32_t &reminderId) const { auto it = notificationBundleOptionMap_.find(reminderId); if (it == notificationBundleOptionMap_.end()) { @@ -220,21 +308,27 @@ bool ReminderDataManager::cmp(sptr &reminderRequest, sptr(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); - CloseReminder(reminderId, cancelNotification); -} - -void ReminderDataManager::CloseReminder(const int32_t &reminderId, bool cancelNotification) -{ sptr reminder = FindReminderRequestLocked(reminderId); if (reminder == nullptr) { ANSR_LOGW("Invilate reminder id: %{public}d", reminderId); return; } - if (activeReminderId_ != -1 && activeReminderId_ == reminderId) { + CloseReminder(reminder, cancelNotification); +} + +void ReminderDataManager::CloseReminder(const sptr &reminder, bool cancelNotification) +{ + int32_t reminderId = reminder->GetReminderId(); + if (activeReminderId_ == reminderId) { ANSR_LOGD("Stop active reminder due to CloseReminder"); - StopTimerLocked(); + StopTimerLocked(TimerType::TRIGGER_TIMER); + } + if (alertingReminderId_ == reminderId) { + StopTimerLocked(TimerType::ALERTING_TIMER); + StopSoundAndVibrationLocked(reminder); } reminder->OnClose(true); + RemoveFromShowedReminders(reminder); if (cancelNotification) { CancelNotification(reminder); } @@ -256,7 +350,7 @@ void ReminderDataManager::RefreshRemindersDueToSysTimeChange(uint8_t type) ANSR_LOGI("Refresh all reminders due to %{public}s changed by user", typeInfo.c_str()); if (activeReminderId_ != -1) { ANSR_LOGD("Stop active reminder due to date/time or timeZone change"); - StopTimerLocked(); + StopTimerLocked(TimerType::TRIGGER_TIMER); } std::vector> showImmediately = RefreshRemindersLocked(type); if (!showImmediately.empty()) { @@ -266,19 +360,62 @@ void ReminderDataManager::RefreshRemindersDueToSysTimeChange(uint8_t type) StartRecentReminder(); } +void ReminderDataManager::TerminateAlerting(const OHOS::EventFwk::Want &want) +{ + int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); + sptr reminder = FindReminderRequestLocked(reminderId); + if (reminder == nullptr) { + ANSR_LOGE("Invilate reminder id: %{public}d", reminderId); + return; + } + TerminateAlerting(reminder, "timeOut"); +} + +void ReminderDataManager::TerminateAlerting(const uint16_t waitInMilli, const sptr &reminder) +{ + sleep(waitInMilli); + TerminateAlerting(reminder, "waitInMillis"); +} + +void ReminderDataManager::TerminateAlerting(const sptr &reminder, const std::string &reason) +{ + ANSR_LOGI("Terminate the alerting reminder, %{public}s, called by %{public}s", + reminder->Dump().c_str(), reason.c_str()); + StopAlertingReminder(reminder); + + if (reminder == nullptr) { + ANSR_LOGE("TerminateAlerting illegal."); + return; + } + if (!reminder->OnTerminate()) { + return; + } + int32_t reminderId = reminder->GetReminderId(); + sptr bundleOption = FindNotificationBundleOption(reminderId); + sptr notificationRequest = reminder->GetNotificationRequest(); + if (bundleOption == nullptr) { + ANSR_LOGE("Get bundle option fail, reminderId=%{public}d", reminderId); + return; + } + ANSR_LOGD("publish(update) notification.(reminderId=%{public}d)", reminder->GetReminderId()); + UpdateNotification(reminder); + advancedNotificationService_->PublishPreparedNotification(notificationRequest, bundleOption); +} + void ReminderDataManager::UpdateAndSaveReminderLocked( const sptr &reminder, const sptr &bundleOption) { std::lock_guard lock(ReminderDataManager::MUTEX); reminder->InitReminderId(); int32_t reminderId = reminder->GetReminderId(); - ANSR_LOGD("Containers(vector/map) add. reminderId=%{public}d", reminderId); + ANSR_LOGD("Containers(map) add. reminderId=%{public}d", reminderId); auto ret = notificationBundleOptionMap_.insert( std::pair>(reminderId, bundleOption)); if (!ret.second) { ANSR_LOGE("Containers add to map error"); return; } + ANSR_LOGD("Containers(vector) add. reminderId=%{public}d", reminderId); reminderVector_.push_back(reminder); totalCount_++; } @@ -288,97 +425,207 @@ void ReminderDataManager::SetService(AdvancedNotificationService *advancedNotifi advancedNotificationService_ = advancedNotificationService; } -void ReminderDataManager::ShowReminder(bool isSysTimeChanged) +void ReminderDataManager::ShowActiveReminder() { - ANSR_LOGD("ShowReminder"); + ANSR_LOGI("Begin to show reminder."); if (activeReminderId_ == -1) { ANSR_LOGE("Active reminder not exist"); return; } - sptr reminder = FindReminderRequestLocked(activeReminderId_); - ShowDesignatedReminderLocked(reminder, isSysTimeChanged); - ResetStates(); + if (HandleSysTimeChange(activeReminder_)) { + ResetStates(TimerType::TRIGGER_TIMER); + return; + } + ShowActiveReminderExtendLocked(activeReminder_); + ResetStates(TimerType::TRIGGER_TIMER); StartRecentReminder(); } -void ReminderDataManager::ShowDesignatedReminderLocked(sptr &reminder, bool isSysTimeChanged) +bool ReminderDataManager::HandleSysTimeChange(const sptr reminder) const +{ + if (reminder->CanShow()) { + return false; + } else { + ANSR_LOGI("handleSystimeChange, no need to show reminder again."); + return true; + } +} + +void ReminderDataManager::SetActiveReminder(const sptr &reminder) +{ + if (reminder == nullptr) { + // activeReminder_ should not be set with null as it point to actual object. + activeReminderId_ = -1; + } else { + activeReminderId_ = reminder->GetReminderId(); + activeReminder_ = reminder; + } +} + +void ReminderDataManager::SetAlertingReminder(const sptr &reminder) +{ + if (reminder == nullptr) { + // alertingReminder_ should not be set with null as it point to actual object. + alertingReminderId_ = -1; + } else { + alertingReminderId_ = reminder->GetReminderId(); + alertingReminder_ = reminder; + } +} + +void ReminderDataManager::ShowActiveReminderExtendLocked(sptr &reminder) { std::lock_guard lock(ReminderDataManager::MUTEX); uint64_t triggerTime = reminder->GetTriggerTimeInMilli(); + bool isAlerting = false; + sptr playSoundReminder = nullptr; for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { if ((*it)->IsExpired()) { continue; } - if ((*it)->GetTriggerTimeInMilli() - triggerTime > ReminderDataManager::SAME_TIME_DISTINGUISH_MILLISECONDS) { + if ((*it)->GetTriggerTimeInMilli() - triggerTime > ReminderRequest::SAME_TIME_DISTINGUISH_MILLISECONDS) { continue; } - if (isSysTimeChanged) { - if ((*it)->GetReminderId() != reminder->GetReminderId()) { - continue; - } - } - int32_t reminderId = (*it)->GetReminderId(); - sptr bundleOption = FindNotificationBundleOption(reminderId); - sptr notificationRequest = (*it)->GetNotificationRequest(); - if (bundleOption == nullptr) { - ANSR_LOGE("Get bundle option fail, reminderId=%{public}d", reminderId); - continue; + if (!isAlerting) { + playSoundReminder = (*it); + isAlerting = true; + } else { + ShowReminder((*it), false, false, false, false); } - if (advancedNotificationService_ == nullptr) { - ANSR_LOGE("ShowReminder fail"); - (*it)->OnShow(isSysTimeChanged, false); + } + if (playSoundReminder != nullptr) { + ShowReminder(playSoundReminder, true, false, false, true); + } +} + +void ReminderDataManager::ShowReminder(const sptr &reminder, const bool &isNeedToPlaySound, + const bool &isNeedToStartNext, const bool &isSysTimeChanged, const bool &needScheduleTimeout) +{ + ANSR_LOGD("Show the reminder(Play sound: %{public}d), %{public}s" + , static_cast(isNeedToPlaySound), reminder->Dump().c_str()); + int32_t reminderId = reminder->GetReminderId(); + sptr bundleOption = FindNotificationBundleOption(reminderId); + sptr notificationRequest = reminder->GetNotificationRequest(); + if (bundleOption == nullptr) { + ANSR_LOGE("Get bundle option fail, reminderId=%{public}d", reminderId); + return; + } + if (advancedNotificationService_ == nullptr) { + ANSR_LOGE("ShowReminder fail"); + reminder->OnShow(false, isSysTimeChanged, false); + return; + } + if (isNeedToPlaySound) { // todo if shouldAlert + PlaySoundAndVibration(reminder); // play sound and vibration + reminder->OnShow(true, isSysTimeChanged, true); + if (needScheduleTimeout) { + StartTimer(reminder, TimerType::ALERTING_TIMER); } else { - ANSR_LOGD("publish notification.(reminderId=%{public}d)", reminderId); - (*it)->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::COMMON, ""); - (*it)->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::REMOVAL_WANT_AGENT, ""); - (*it)->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::ACTION_BUTTON, ""); - advancedNotificationService_->PublishPreparedNotification(notificationRequest, bundleOption); - (*it)->OnShow(isSysTimeChanged, true); - HandleSameNotificationIdShowing((*it)); + TerminateAlerting(ReminderRequest::MILLI_SECONDS, reminder); } + } else { + reminder->OnShow(false, isSysTimeChanged, true); + } + AddToShowedReminders(reminder); + ANSR_LOGD("publish notification.(reminderId=%{public}d)", reminder->GetReminderId()); + UpdateNotification(reminder); // this should be called after OnShow + ErrCode errCode + = advancedNotificationService_->PublishPreparedNotification(notificationRequest, bundleOption); + if (errCode != ERR_OK) { + reminder->OnShowFail(); + RemoveFromShowedReminders(reminder); + } else { + HandleSameNotificationIdShowing(reminder); + } + if (isNeedToStartNext) { + StartRecentReminder(); } } -void ReminderDataManager::StartRecentReminder() +void ReminderDataManager::UpdateNotification(const sptr &reminder) { - sptr reminder = GetRecentReminderLocked(); + reminder->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::COMMON, ""); + reminder->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::REMOVAL_WANT_AGENT, ""); + reminder->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::WANT_AGENT, ""); + reminder->UpdateNotificationRequest(ReminderRequest::UpdateNotificationType::MAX_SCREEN_WANT_AGENT, ""); +} + +void ReminderDataManager::SnoozeReminder(const OHOS::EventFwk::Want &want) +{ + int32_t reminderId = static_cast(want.GetIntParam(ReminderRequest::PARAM_REMINDER_ID, -1)); + sptr reminder = FindReminderRequestLocked(reminderId); if (reminder == nullptr) { - ANSR_LOGI("No reminder need to start"); + ANSR_LOGW("Invilate reminder id: %{public}d", reminderId); return; } + SnoozeReminderImpl(reminder); +} - bool toStart = true; - if (activeReminderId_ != -1) { - if (activeReminderId_ != reminder->GetReminderId()) { - ANSR_LOGI("Stop active reminder"); - StopTimerLocked(); - } else { - ANSR_LOGI("Recent reminder has already run, no need to start again."); - toStart = false; - } +void ReminderDataManager::SnoozeReminderImpl(sptr &reminder) +{ + ANSR_LOGI("Snooze the reminder request, %{public}s", reminder->Dump().c_str()); + int32_t reminderId = reminder->GetReminderId(); + if (activeReminderId_ == reminderId) { + ANSR_LOGD("Cancel active reminder, id=%{public}d", activeReminderId_); + StopTimerLocked(TimerType::TRIGGER_TIMER); } - if (toStart) { - ANSR_LOGI("Start recent reminder"); - StartTimerLocked(reminder); + + // 1) Snooze the reminder by manual + if (alertingReminderId_ == reminder->GetReminderId()) { + StopTimerLocked(TimerType::ALERTING_TIMER); + StopSoundAndVibrationLocked(reminder); } + reminder->OnSnooze(); + + // 2) Show the notification dialog in the systemUI + sptr bundleOption = FindNotificationBundleOption(reminderId); + sptr notificationRequest = reminder->GetNotificationRequest(); + if (bundleOption == nullptr) { + ANSR_LOGW("snoozeReminder, invalid bundle option"); + return; + } + ANSR_LOGD("publish(update) notification.(reminderId=%{public}d)", reminder->GetReminderId()); + UpdateNotification(reminder); + advancedNotificationService_->PublishPreparedNotification(notificationRequest, bundleOption); + StartRecentReminder(); } -void ReminderDataManager::StopTimer() +// snoozeReminder(bool snoozeAll) + +void ReminderDataManager::StartRecentReminder() { - if (timerId_ == 0) { - ANSR_LOGD("Timer is not running"); + sptr reminder = GetRecentReminderLocked(); + if (reminder == nullptr) { + ANSR_LOGI("No reminder need to start"); + SetActiveReminder(reminder); return; } - ANSR_LOGD("Stop timer id=%{public}llu", (unsigned long long)timerId_); - sptr timer = MiscServices::TimeServiceClient::GetInstance(); - timer->StopTimer(timerId_); - ResetStates(); + if (activeReminderId_ == reminder->GetReminderId()) { + ANSR_LOGI("Recent reminder has already run, no need to start again."); + return; + } + if (activeReminderId_ != -1) { + StopTimerLocked(TimerType::TRIGGER_TIMER); + activeReminder_->OnStop(); + } + ANSR_LOGI("Start recent reminder"); + StartTimerLocked(reminder, TimerType::TRIGGER_TIMER); + reminder->OnStart(); + SetActiveReminder(reminder); } -void ReminderDataManager::StopTimerLocked() +void ReminderDataManager::StopAlertingReminder(const sptr &reminder) { - std::lock_guard lock(ReminderDataManager::MUTEX); - StopTimer(); + if (reminder == nullptr) { + ANSR_LOGE("StopAlertingReminder illegal."); + return; + } + if (alertingReminderId_ == -1 || reminder->GetReminderId() != alertingReminderId_) { + ANSR_LOGE("StopAlertingReminder is illegal."); + return; + } + StopSoundAndVibration(alertingReminder_); + StopTimer(TimerType::ALERTING_TIMER); } std::string ReminderDataManager::Dump() const @@ -435,27 +682,27 @@ sptr ReminderDataManager::GetRecentReminderLocked() { std::lock_guard lock(ReminderDataManager::MUTEX); sort(reminderVector_.begin(), reminderVector_.end(), cmp); - for (auto reminder = reminderVector_.begin(); reminder != reminderVector_.end();) { - if (!(*reminder)->IsExpired()) { - ANSR_LOGD("GetRecentReminderLocked: %{public}s", (*reminder)->Dump().c_str()); - return *reminder; - } - if (!(*reminder)->CanRemove()) { - ANSR_LOGD("Reminder has been expired: %{public}s", (*reminder)->Dump().c_str()); - reminder++; + for (auto it = reminderVector_.begin(); it != reminderVector_.end();) { + if (!(*it)->IsExpired()) { + ANSR_LOGI("GetRecentReminderLocked: %{public}s", (*it)->Dump().c_str()); + return *it; + } + if (!(*it)->CanRemove()) { + ANSR_LOGD("Reminder has been expired: %{public}s", (*it)->Dump().c_str()); + it++; continue; } - int32_t reminderId = (*reminder)->GetReminderId(); + int32_t reminderId = (*it)->GetReminderId(); ANSR_LOGD("Containers(vector) remove. reminderId=%{public}d", reminderId); - auto it = notificationBundleOptionMap_.find((*reminder)->GetReminderId()); - if (it == notificationBundleOptionMap_.end()) { + auto mit = notificationBundleOptionMap_.find((*it)->GetReminderId()); + if (mit == notificationBundleOptionMap_.end()) { ANSR_LOGE("Remove notificationBundleOption(reminderId=%{public}d) fail", - (*reminder)->GetReminderId()); + (*it)->GetReminderId()); } else { - ANSR_LOGD("Containers(map) remove. reminderId=%{public}d", reminderId); - notificationBundleOptionMap_.erase(it); + ANSR_LOGD("Containers(vector/map) remove. reminderId=%{public}d", reminderId); + notificationBundleOptionMap_.erase(mit); } - reminder = reminderVector_.erase(reminder); + it = reminderVector_.erase(it); totalCount_--; } return nullptr; @@ -482,13 +729,21 @@ std::vector> ReminderDataManager::GetSameBundleRemindersLo void ReminderDataManager::HandleImmediatelyShow( std::vector> &showImmediately, bool isSysTimeChanged) { + bool isAlerting = false; for (auto it = showImmediately.begin(); it != showImmediately.end(); ++it) { - ShowDesignatedReminderLocked((*it), isSysTimeChanged); + if (!isAlerting) { + ShowReminder((*it), true, false, isSysTimeChanged, false); + isAlerting = true; + } else { + ShowReminder((*it), false, false, isSysTimeChanged, false); + } } } sptr ReminderDataManager::HandleRefreshReminder(uint8_t &type, sptr &reminder) { + reminder->SetReminderTimeInMilli(ReminderRequest::INVALID_LONG_LONG_VALUE); + uint64_t triggerTimeBefore = reminder->GetTriggerTimeInMilli(); bool needShowImmediately = false; if (type == TIME_ZONE_CHANGE) { needShowImmediately = reminder->OnTimeZoneChange(); @@ -497,6 +752,11 @@ sptr ReminderDataManager::HandleRefreshReminder(uint8_t &type, needShowImmediately = reminder->OnDateTimeChange(); } if (!needShowImmediately) { + uint64_t triggerTimeAfter = reminder->GetTriggerTimeInMilli(); + if (triggerTimeBefore != triggerTimeAfter + || reminder->GetReminderId() == alertingReminderId_) { + CloseReminder(reminder, true); + } return nullptr; } else { return reminder; @@ -505,7 +765,7 @@ sptr ReminderDataManager::HandleRefreshReminder(uint8_t &type, void ReminderDataManager::HandleSameNotificationIdShowing(const sptr reminder) { - // not add ReminderDataManager::MUTEX, as ShowDesignatedReminderLocked has locked + // not add ReminderDataManager::MUTEX, as ShowActiveReminderExtendLocked has locked int32_t notificationId = reminder->GetNotificationId(); ANSR_LOGD("HandleSameNotificationIdShowing notificationId=%{public}d", notificationId); int32_t curReminderId = reminder->GetReminderId(); @@ -524,7 +784,11 @@ void ReminderDataManager::HandleSameNotificationIdShowing(const sptrGetNotificationId() && IsBelongToSameApp(reminder, bundleOption->GetBundleName(), 0)) { + if ((*it)->IsAlerting()) { + StopAlertingReminder(*it); + } (*it)->OnSameNotificationIdCovered(); + RemoveFromShowedReminders(*it); } } } @@ -545,6 +809,87 @@ bool ReminderDataManager::IsBelongToSameApp( return false; } +void ReminderDataManager::PlaySoundAndVibrationLocked(const sptr &reminder) +{ + std::lock_guard lock(ReminderDataManager::ALERT_MUTEX); // todo check died lock + PlaySoundAndVibration(reminder); +} + +void ReminderDataManager::PlaySoundAndVibration(const sptr &reminder) +{ + if (reminder == nullptr) { + ANSR_LOGE("Play sound and vibration failed as reminder is null."); + return; + } + if (alertingReminderId_ != -1) { + TerminateAlerting(alertingReminder_, "PlaySoundAndVibration"); + } + ANSR_LOGD("Play sound and vibration, reminderId=%{public}d", reminder->GetReminderId()); + if (soundPlayer_ == nullptr) { + soundPlayer_ = Media::PlayerFactory::CreatePlayer(); + } + std::string uri = GetSoundUri(reminder); + ANSR_LOGD("uri:%{public}s", uri.c_str()); + soundPlayer_->SetSource(uri); + soundPlayer_->SetLooping(true); + soundPlayer_->Prepare(); + soundPlayer_->Play(); + SetAlertingReminder(reminder); +} + +std::string ReminderDataManager::GetSoundUri(const sptr &reminder) +{ + sptr bundle = FindNotificationBundleOption(reminder->GetReminderId()); + std::vector> slots; + ErrCode errCode = advancedNotificationService_->GetSlotsByBundle(bundle, slots); + Uri uri = DEFAULT_NOTIFICATION_SOUND; + if (errCode != ERR_OK) { + ANSR_LOGW("Get sound uri fail, use default sound instead."); + return uri.GetSchemeSpecificPart(); + } + for (auto it = slots.begin(); it != slots.end(); ++it) { + if ((*it)->GetType() == reminder->GetSlotType()) { + uri = (*it)->GetSound(); + break; + } + } + return uri.GetSchemeSpecificPart(); +} + +void ReminderDataManager::StopSoundAndVibrationLocked(const sptr &reminder) +{ + std::lock_guard lock(ReminderDataManager::ALERT_MUTEX); + StopSoundAndVibration(reminder); +} + +void ReminderDataManager::StopSoundAndVibration(const sptr &reminder) +{ + if (reminder == nullptr) { + ANSR_LOGE("Stop sound and vibration failed as reminder is null."); + return; + } + if (alertingReminderId_ == -1 || (reminder->GetReminderId() != alertingReminderId_)) { + ANSR_LOGE("Stop sound and vibration failed as alertingReminder is illegal."); + return; + } + ANSR_LOGD("Stop sound and vibration, reminderId=%{public}d", reminder->GetReminderId()); + soundPlayer_->Stop(); + sptr nullReminder = nullptr; + SetAlertingReminder(nullReminder); +} + +void ReminderDataManager::RemoveFromShowedReminders(const sptr &reminder) +{ + std::lock_guard lock(ReminderDataManager::SHOW_MUTEX); + for (auto it = shownReminderVector_.begin(); it != shownReminderVector_.end(); ++it) { + if ((*it)->GetReminderId() == reminder->GetReminderId()) { + ANSR_LOGD("Containers(shownVector) remove. reminderId=%{public}d", reminder->GetReminderId()); + shownReminderVector_.erase(it); + break; + } + } +} + std::vector> ReminderDataManager::RefreshRemindersLocked(uint8_t type) { std::lock_guard lock(ReminderDataManager::MUTEX); @@ -566,7 +911,6 @@ void ReminderDataManager::RemoveReminderLocked(const int32_t &reminderId) ANSR_LOGD("Containers(vector) remove. reminderId=%{public}d", reminderId); it = reminderVector_.erase(it); totalCount_--; - ANSR_LOGD("Remove reminder(id=%{public}d) success", reminderId); break; } else { ++it; @@ -576,26 +920,117 @@ void ReminderDataManager::RemoveReminderLocked(const int32_t &reminderId) if (it == notificationBundleOptionMap_.end()) { ANSR_LOGE("Remove notificationBundleOption(reminderId=%{public}d) fail", reminderId); } else { - ANSR_LOGD("Containers(map) remove: reminderId=%{public}d", reminderId); + ANSR_LOGD("Containers(map) remove. reminderId=%{public}d", reminderId); notificationBundleOptionMap_.erase(it); } } -void ReminderDataManager::ResetStates() +void ReminderDataManager::StartTimerLocked(const sptr &reminderRequest, TimerType type) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + StartTimer(reminderRequest, type); +} + +void ReminderDataManager::StartTimer(const sptr &reminderRequest, TimerType type) { - ANSR_LOGD("ResetStates"); - timerId_ = 0; - activeReminderId_ = -1; + sptr timer = MiscServices::TimeServiceClient::GetInstance(); + time_t now; + (void)time(&now); // unit is seconds. + uint64_t triggerTime = 0; + switch (type) { + case TimerType::TRIGGER_TIMER: { + if (timerId_ != 0) { + ANSR_LOGE("Trigger timer has already started."); + break; + } + triggerTime = reminderRequest->GetTriggerTimeInMilli(); + timerId_ = timer->CreateTimer(REMINDER_DATA_MANAGER->CreateTimerInfo(type)); + timer->StartTimer(timerId_, triggerTime); + SetActiveReminder(reminderRequest); + ANSR_LOGD("Start timing (next triggerTime), timerId=%{public}llu", (unsigned long long)timerId_); + break; + } + case TimerType::ALERTING_TIMER: { + if (timerIdAlerting_ != 0) { + ANSR_LOGE("Alerting time out timer has already started."); + break; + } + triggerTime = now * ReminderRequest::MILLI_SECONDS + + static_cast(reminderRequest->GetRingDuration() * ReminderRequest::MILLI_SECONDS); + timerIdAlerting_ = timer->CreateTimer(REMINDER_DATA_MANAGER->CreateTimerInfo(type)); + timer->StartTimer(timerIdAlerting_, triggerTime); + ANSR_LOGD( + "Start timing (alerting time out), timerId=%{public}llu", (unsigned long long)timerIdAlerting_); + break; + } + default: { + ANSR_LOGE("TimerType not support"); + break; + } + } + if (triggerTime == 0) { + ANSR_LOGW("Start timer fail"); + } else { + ANSR_LOGD("Timing info: now:(%{public}lld), tar:(%{public}llu)", + (long long)(now * ReminderRequest::MILLI_SECONDS), (unsigned long long)(triggerTime)); + } } -void ReminderDataManager::StartTimerLocked(sptr &reminderRequest) +void ReminderDataManager::StopTimerLocked(TimerType type) { - ANSR_LOGD("Start timer: millSeconds=%{public}llu", (unsigned long long)(reminderRequest->GetTriggerTimeInMilli())); std::lock_guard lock(ReminderDataManager::MUTEX); + StopTimer(type); +} + +void ReminderDataManager::StopTimer(TimerType type) +{ sptr timer = MiscServices::TimeServiceClient::GetInstance(); - timerId_ = timer->CreateTimer(REMINDER_DATA_MANAGER->CreateTimerInfo()); - timer->StartTimer(timerId_, reminderRequest->GetTriggerTimeInMilli()); - activeReminderId_ = reminderRequest->GetReminderId(); + uint64_t timerId = 0; + switch (type) { + case TimerType::TRIGGER_TIMER: { + timerId = timerId_; + ANSR_LOGD("Stop timing (next triggerTime)"); + break; + } + case TimerType::ALERTING_TIMER: { + timerId = timerIdAlerting_; + ANSR_LOGD("Stop timing (alerting time out)"); + break; + } + default: { + ANSR_LOGE("TimerType not support"); + break; + } + } + if (timerId == 0) { + ANSR_LOGD("Timer is not running"); + return; + } + ANSR_LOGD("Stop timer id=%{public}llu", (unsigned long long)timerId); + timer->StopTimer(timerId); + ResetStates(type); +} + +void ReminderDataManager::ResetStates(TimerType type) +{ + switch (type) { + case TimerType::TRIGGER_TIMER: { + ANSR_LOGD("ResetStates(activeReminder)"); + timerId_ = 0; + activeReminderId_ = -1; + break; + } + case TimerType::ALERTING_TIMER: { + ANSR_LOGD("ResetStates(alertingReminder)"); + timerIdAlerting_ = 0; + alertingReminderId_ = -1; + break; + } + default: { + ANSR_LOGE("TimerType not support"); + break; + } + } } } } \ No newline at end of file diff --git a/services/ans/src/reminder_event_manager.cpp b/services/ans/src/reminder_event_manager.cpp index 117c8312cec2c0003bc02c3f809ab51bab60ced6..d085adff048081db48272588c9c02c2fa3b4621d 100644 --- a/services/ans/src/reminder_event_manager.cpp +++ b/services/ans/src/reminder_event_manager.cpp @@ -14,9 +14,14 @@ */ #include "ans_log_wrapper.h" +#include "appmgr/app_mgr_constants.h" +#include "bundle_mgr_interface.h" #include "common_event_manager.h" #include "common_event_support.h" #include "bundle_constants.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" #include "reminder_event_manager.h" @@ -32,7 +37,9 @@ void ReminderEventManager::init(std::shared_ptr &reminderDa { MatchingSkills matchingSkills; matchingSkills.AddEvent(ReminderRequest::REMINDER_EVENT_ALARM_ALERT); + matchingSkills.AddEvent(ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT); matchingSkills.AddEvent(ReminderRequest::REMINDER_EVENT_CLOSE_ALERT); + matchingSkills.AddEvent(ReminderRequest::REMINDER_EVENT_SNOOZE_ALERT); matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED); matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_RESTARTED); @@ -58,34 +65,37 @@ void ReminderEventManager::ReminderEventSubscriber::OnReceiveEvent(const EventFw { Want want = data.GetWant(); std::string action = want.GetAction(); - ANSR_LOGD("Recieved common event:%{public}s", action.c_str()); + ANSR_LOGI("Recieved common event:%{public}s", action.c_str()); if (action == ReminderRequest::REMINDER_EVENT_ALARM_ALERT) { - reminderDataManager_->ShowReminder(false); + reminderDataManager_->ShowActiveReminder(); + return; + } + if (action == ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT) { + reminderDataManager_->TerminateAlerting(want); return; } if (action == ReminderRequest::REMINDER_EVENT_CLOSE_ALERT) { reminderDataManager_->CloseReminder(want, true); return; } + if (action == ReminderRequest::REMINDER_EVENT_SNOOZE_ALERT) { + reminderDataManager_->SnoozeReminder(want); + return; + } if (action == ReminderRequest::REMINDER_EVENT_REMOVE_NOTIFICATION) { reminderDataManager_->CloseReminder(want, false); return; } if (action == CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) { - OHOS::AppExecFwk::ElementName ele = want.GetElement(); - std::string bundleName = ele.GetBundleName(); - int uid = want.GetIntParam(OHOS::AppExecFwk::Constants::UID, -1); - ANSR_LOGD("bundleName=%{public}s, uid=%{public}d", bundleName.c_str(), uid); - sptr bundleOption = new NotificationBundleOption(bundleName, uid); - reminderDataManager_->CancelAllReminders(bundleOption); + HandlePackageRemove(want); return; } if (action == CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED) { - // todo + HandlePackageRemove(want); return; } if (action == CommonEventSupport::COMMON_EVENT_PACKAGE_RESTARTED) { - // todo + HandleProcessDied(want); return; } if (action == CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED) { @@ -97,5 +107,43 @@ void ReminderEventManager::ReminderEventSubscriber::OnReceiveEvent(const EventFw return; } } + +void ReminderEventManager::ReminderEventSubscriber::HandlePackageRemove(OHOS::EventFwk::Want &want) const +{ + sptr bundleOption = GetBundleOption(want); + reminderDataManager_->CancelAllReminders(bundleOption); +} + +void ReminderEventManager::ReminderEventSubscriber::HandleProcessDied(OHOS::EventFwk::Want &want) const +{ + sptr bundleOption = GetBundleOption(want); + reminderDataManager_->OnProcessDiedLocked(bundleOption); +} + +sptr ReminderEventManager::ReminderEventSubscriber::GetBundleOption( + const OHOS::EventFwk::Want &want) const +{ + OHOS::AppExecFwk::ElementName ele = want.GetElement(); + std::string bundleName = ele.GetBundleName(); + int userId = want.GetIntParam(OHOS::AppExecFwk::Constants::USER_ID, -1); + int32_t uid = GetUid(userId, bundleName); + ANSR_LOGD("bundleName=%{public}s, uid=%{public}d", bundleName.c_str(), uid); + sptr bundleOption = new NotificationBundleOption(bundleName, uid); + return bundleOption; +} + +int32_t ReminderEventManager::ReminderEventSubscriber::GetUid(const int userId, const std::string bundleName) const +{ + AppExecFwk::ApplicationInfo info; + OHOS::sptr systemAbilityManager + = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr remoteObject + = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + OHOS::sptr bundleMgr + = OHOS::iface_cast(remoteObject); + bundleMgr->GetApplicationInfo(bundleName, AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, + static_cast(userId), info); + return static_cast(info.uid); +} } // namespace OHOS -} // namespace Notification \ No newline at end of file +} // namespace Notification diff --git a/services/ans/src/reminder_timer_info.cpp b/services/ans/src/reminder_timer_info.cpp index 3c7c39c873573b5cf5bb7eb3e060afa287ec62ce..486ae1d0012ab1a48769c51e9361ca785fdad3c3 100644 --- a/services/ans/src/reminder_timer_info.cpp +++ b/services/ans/src/reminder_timer_info.cpp @@ -44,19 +44,7 @@ void ReminderTimerInfo::SetWantAgent(std::shared_ptr