/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "reminder_request.h" #include "reminder_table.h" #include "ans_const_define.h" #include "ans_log_wrapper.h" #include "bundle_mgr_interface.h" #include "bundle_mgr_proxy.h" #include "if_system_ability_manager.h" #include "ipc_skeleton.h" #include "iservice_registry.h" #include "locale_config.h" #include "os_account_manager.h" #include "reminder_store.h" #include "system_ability_definition.h" #include "want_agent_helper.h" #include "nlohmann/json.hpp" namespace OHOS { namespace Notification { namespace { const int32_t BASE_YEAR = 1900; const int32_t SINGLE_BUTTON_INVALID = 0; const int32_t SINGLE_BUTTON_JSONSTRING = 0; const int32_t SINGLE_BUTTON_ONLY_ONE = 1; const int32_t SINGLE_BUTTON_MIN_LEN = 2; const int32_t SINGLE_BUTTON_MAX_LEN = 4; const int32_t BUTTON_TYPE_INDEX = 0; const int32_t BUTTON_TITLE_INDEX = 1; const int32_t BUTTON_PKG_INDEX = 2; const int32_t BUTTON_ABILITY_INDEX = 3; const int32_t WANT_AGENT_URI_INDEX = 2; const int32_t INDENT = -1; } int32_t ReminderRequest::GLOBAL_ID = 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 uint8_t ReminderRequest::TIME_HOUR_OFFSET = 12; 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"; const std::string ReminderRequest::REMINDER_EVENT_SNOOZE_ALERT = "ohos.event.notification.reminder.SNOOZE_ALERT"; const std::string ReminderRequest::REMINDER_EVENT_CUSTOM_ALERT = "ohos.event.notification.reminder.COSTUM_ALERT"; const std::string ReminderRequest::REMINDER_EVENT_ALERT_TIMEOUT = "ohos.event.notification.reminder.ALERT_TIMEOUT"; const std::string ReminderRequest::REMINDER_EVENT_REMOVE_NOTIFICATION = "ohos.event.notification.reminder.REMOVE_NOTIFICATION"; const std::string ReminderRequest::PARAM_REMINDER_ID = "REMINDER_ID"; const std::string ReminderRequest::SEP_BUTTON_SINGLE = ""; const std::string ReminderRequest::SEP_BUTTON_MULTI = ""; const std::string ReminderRequest::SEP_WANT_AGENT = ""; const std::string ReminderRequest::SEP_BUTTON_VALUE_TYPE = ""; const std::string ReminderRequest::SEP_BUTTON_VALUE = ""; const std::string ReminderRequest::SEP_BUTTON_VALUE_BLOB = ""; const uint8_t ReminderRequest::DAYS_PER_WEEK = 7; const uint8_t ReminderRequest::MONDAY = 1; const uint8_t ReminderRequest::SUNDAY = 7; const uint8_t ReminderRequest::HOURS_PER_DAY = 24; const uint16_t ReminderRequest::SECONDS_PER_HOUR = 3600; std::string ReminderRequest::sqlOfAddColumns = ""; std::vector ReminderRequest::columns; ReminderRequest::ReminderRequest() { InitServerObj(); } ReminderRequest::ReminderRequest(const ReminderRequest &other) { 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->isSystemApp_ = other.isSystemApp_; 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->snoozeSlotType_ = other.snoozeSlotType_; this->notificationRequest_ = other.notificationRequest_; this->wantAgentInfo_ = other.wantAgentInfo_; this->maxScreenWantAgentInfo_ = other.maxScreenWantAgentInfo_; this->actionButtonMap_ = other.actionButtonMap_; this->tapDismissed_= other.tapDismissed_; this->autoDeletedTime_ = other.autoDeletedTime_; this->customButtonUri_ = other.customButtonUri_; this->repeatDaysOfWeek_ = other.repeatDaysOfWeek_; this->groupId_ = other.groupId_; this->customRingUri_ = other.customRingUri_; this->creatorBundleName_ = other.creatorBundleName_; } ReminderRequest::ReminderRequest(int32_t reminderId) { reminderId_ = reminderId; InitServerObj(); } ReminderRequest::ReminderRequest(ReminderType reminderType) { reminderType_ = reminderType; InitServerObj(); } bool ReminderRequest::CanRemove() const { 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 { const time_t nextTriggerTime = static_cast(triggerTimeInMilli_ / MILLI_SECONDS); std::string dateTimeInfo = GetTimeInfoInner(nextTriggerTime, TimeFormat::YMDHMS, true); return "Reminder[" "reminderId=" + std::to_string(reminderId_) + ", type=" + std::to_string(static_cast(reminderType_)) + ", state=" + GetState(state_) + ", nextTriggerTime=" + dateTimeInfo.c_str() + "]"; } ReminderRequest& ReminderRequest::SetActionButton(const std::string &title, const ActionButtonType &type, const std::string &resource, const std::shared_ptr &buttonWantAgent, const std::shared_ptr &buttonDataShareUpdate) { if ((type != ActionButtonType::CLOSE) && (type != ActionButtonType::SNOOZE) && (type != ActionButtonType::CUSTOM)) { ANSR_LOGI("Button type is not support: %{public}d.", static_cast(type)); return *this; } ActionButtonInfo actionButtonInfo; actionButtonInfo.type = type; actionButtonInfo.title = title; actionButtonInfo.resource = resource; actionButtonInfo.wantAgent = buttonWantAgent; actionButtonInfo.dataShareUpdate = buttonDataShareUpdate; actionButtonMap_.insert(std::pair(type, actionButtonInfo)); return *this; } ReminderRequest& ReminderRequest::SetContent(const std::string &content) { content_ = content; return *this; } ReminderRequest& ReminderRequest::SetExpiredContent(const std::string &expiredContent) { expiredContent_ = expiredContent; return *this; } void ReminderRequest::SetExpired(bool isExpired) { isExpired_ = isExpired; } void ReminderRequest::InitCreatorBundleName(const std::string &creatorBundleName) { creatorBundleName_ = creatorBundleName; } void ReminderRequest::InitReminderId() { std::lock_guard lock(std::mutex); if (GLOBAL_ID < 0) { ANSR_LOGW("GLOBAL_ID overdule"); GLOBAL_ID = 0; } reminderId_ = ++GLOBAL_ID; ANSR_LOGI("reminderId_=%{public}d", reminderId_); } void ReminderRequest::InitUserId(const int32_t &userId) { userId_ = userId; } void ReminderRequest::InitUid(const int32_t &uid) { uid_ = uid; } void ReminderRequest::InitBundleName(const std::string &bundleName) { bundleName_ = bundleName; } bool ReminderRequest::IsExpired() const { return isExpired_; } bool ReminderRequest::IsShowing() const { if ((state_ & REMINDER_STATUS_SHOWING) != 0) { return true; } return false; } void ReminderRequest::OnClose(bool updateNext) { if ((state_ & REMINDER_STATUS_SHOWING) == 0) { ANSR_LOGE("onClose, the state of reminder is incorrect, state:%{public}s", GetState(state_).c_str()); return; } 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(true, false); if (nextTriggerTime == INVALID_LONG_LONG_VALUE) { isExpired_ = true; } else { SetTriggerTimeInMilli(nextTriggerTime); snoozeTimesDynamic_ = snoozeTimes_; } } } bool ReminderRequest::OnDateTimeChange() { uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(true, false); return HandleSysTimeChange(triggerTimeInMilli_, nextTriggerTime); } bool ReminderRequest::HandleSysTimeChange(uint64_t oriTriggerTime, uint64_t optTriggerTime) { if (isExpired_) { return false; } uint64_t now = GetNowInstantMilli(); if (now == 0) { ANSR_LOGE("get now time failed."); return false; } if (oriTriggerTime == 0 && optTriggerTime < now) { ANSR_LOGW("trigger time is less than now time."); return false; } bool showImmediately = false; if (optTriggerTime != INVALID_LONG_LONG_VALUE && (optTriggerTime <= oriTriggerTime || oriTriggerTime == 0)) { // case1. switch to a previous time SetTriggerTimeInMilli(optTriggerTime); snoozeTimesDynamic_ = snoozeTimes_; } else { 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. showImmediately = false; } } return showImmediately; } bool ReminderRequest::HandleTimeZoneChange( uint64_t oldZoneTriggerTime, uint64_t newZoneTriggerTime, uint64_t optTriggerTime) { if (isExpired_) { return false; } ANSR_LOGD("Handle timezone change, old:%{public}" PRIu64 ", new:%{public}" PRIu64 "", oldZoneTriggerTime, newZoneTriggerTime); if (oldZoneTriggerTime == newZoneTriggerTime) { return false; } bool showImmediately = false; 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; (void)time(&now); // unit is seconds. if (static_cast(now) < 0) { ANSR_LOGE("Get now time error"); return false; } if (newZoneTriggerTime <= GetDurationSinceEpochInMilli(now)) { snoozeTimesDynamic_ = 0; showImmediately = true; } else { SetTriggerTimeInMilli(newZoneTriggerTime); showImmediately = false; } } return showImmediately; } void ReminderRequest::OnSameNotificationIdCovered() { SetState(false, REMINDER_STATUS_ALERTING | REMINDER_STATUS_SHOWING | REMINDER_STATUS_SNOOZE, "OnSameNotificationIdCovered"); } 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(); } } 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()"); } SetSnoozeTimesDynamic(GetSnoozeTimes()); 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() { time_t oldZoneTriggerTime = static_cast(triggerTimeInMilli_ / MILLI_SECONDS); struct tm oriTime; (void)gmtime_r(&oldZoneTriggerTime, &oriTime); time_t newZoneTriggerTime = mktime(&oriTime); uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(true, false); return HandleTimeZoneChange( triggerTimeInMilli_, GetDurationSinceEpochInMilli(newZoneTriggerTime), nextTriggerTime); } int64_t ReminderRequest::RecoverInt64FromDb(const std::shared_ptr &resultSet, const std::string &columnName, const DbRecoveryType &columnType) { if (resultSet == nullptr) { ANSR_LOGE("ResultSet is null"); return 0; } switch (columnType) { case (DbRecoveryType::INT): { int32_t value; ReminderStore::GetInt32Val(resultSet, columnName, value); return static_cast(value); } case (DbRecoveryType::LONG): { int64_t value; ReminderStore::GetInt64Val(resultSet, columnName, value); return value; } default: { ANSR_LOGD("ColumnType not support."); break; } } ANSR_LOGE("Recover data error"); return 0; } void ReminderRequest::RecoverBasicFromDb(const std::shared_ptr& resultSet) { // reminderId ReminderStore::GetInt32Val(resultSet, ReminderTable::REMINDER_ID, reminderId_); // userId ReminderStore::GetInt32Val(resultSet, ReminderTable::USER_ID, userId_); // bundleName ReminderStore::GetStringVal(resultSet, ReminderTable::PKG_NAME, bundleName_); // uid ReminderStore::GetInt32Val(resultSet, ReminderTable::UID, uid_); // isSystemApp std::string isSysApp; ReminderStore::GetStringVal(resultSet, ReminderTable::SYS_APP, isSysApp); isSystemApp_ = isSysApp == "true" ? true : false; // reminderType int32_t reminderType; ReminderStore::GetInt32Val(resultSet, ReminderTable::REMINDER_TYPE, reminderType); reminderType_ = ReminderType(reminderType); // reminderTime reminderTimeInMilli_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::REMINDER_TIME, DbRecoveryType::LONG)); // triggerTime triggerTimeInMilli_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::TRIGGER_TIME, DbRecoveryType::LONG)); // timeInterval uint64_t timeIntervalInSecond = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::TIME_INTERVAL, DbRecoveryType::LONG)); SetTimeInterval(timeIntervalInSecond); // snoozeTimes snoozeTimes_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::SNOOZE_TIMES, DbRecoveryType::INT)); // dynamicSnoozeTimes snoozeTimesDynamic_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::DYNAMIC_SNOOZE_TIMES, DbRecoveryType::INT)); // ringDuration uint64_t ringDurationInSecond = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::RING_DURATION, DbRecoveryType::LONG)); SetRingDuration(ringDurationInSecond); // isExpired std::string isExpired; ReminderStore::GetStringVal(resultSet, ReminderTable::IS_EXPIRED, isExpired); isExpired_ = isExpired == "true" ? true : false; // state state_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::STATE, DbRecoveryType::INT)); // repeatDaysOfWeek_ repeatDaysOfWeek_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::REPEAT_DAYS_OF_WEEK, DbRecoveryType::INT)); // action buttons RecoverActionButton(resultSet); // slotType int32_t slotType; ReminderStore::GetInt32Val(resultSet, ReminderTable::SLOT_ID, slotType); slotType_ = NotificationConstant::SlotType(slotType); // snoozeSlotType int32_t snoozeSlotType; ReminderStore::GetInt32Val(resultSet, ReminderTable::SNOOZE_SLOT_ID, snoozeSlotType); snoozeSlotType_ = NotificationConstant::SlotType(snoozeSlotType); // notification id ReminderStore::GetInt32Val(resultSet, ReminderTable::NOTIFICATION_ID, notificationId_); // title ReminderStore::GetStringVal(resultSet, ReminderTable::TITLE, title_); // content ReminderStore::GetStringVal(resultSet, ReminderTable::CONTENT, content_); // snoozeContent ReminderStore::GetStringVal(resultSet, ReminderTable::SNOOZE_CONTENT, snoozeContent_); // expiredContent ReminderStore::GetStringVal(resultSet, ReminderTable::EXPIRED_CONTENT, expiredContent_); InitNotificationRequest(); // must set before wantAgent & maxScreenWantAgent } void ReminderRequest::RecoverFromDb(const std::shared_ptr &resultSet) { if (resultSet == nullptr) { ANSR_LOGE("ResultSet is null"); return; } RecoverBasicFromDb(resultSet); // wantAgent std::string wantAgent; ReminderStore::GetStringVal(resultSet, ReminderTable::AGENT, wantAgent); RecoverWantAgent(wantAgent, 0); // maxScreenWantAgent std::string maxScreenWantAgent; ReminderStore::GetStringVal(resultSet, ReminderTable::MAX_SCREEN_AGENT, maxScreenWantAgent); RecoverWantAgent(maxScreenWantAgent, 1); // tapDismissed std::string tapDismissed; ReminderStore::GetStringVal(resultSet, ReminderTable::TAP_DISMISSED, tapDismissed); tapDismissed_ = tapDismissed == "true" ? true : false; // autoDeletedTime autoDeletedTime_ = static_cast(RecoverInt64FromDb(resultSet, ReminderTable::AUTO_DELETED_TIME, DbRecoveryType::LONG)); // customButtonUri ReminderStore::GetStringVal(resultSet, ReminderTable::CUSTOM_BUTTON_URI, customButtonUri_); // groupId ReminderStore::GetStringVal(resultSet, ReminderTable::GROUP_ID, groupId_); // customRingUri ReminderStore::GetStringVal(resultSet, ReminderTable::CUSTOM_RING_URI, customRingUri_); // creatorBundleName ReminderStore::GetStringVal(resultSet, ReminderTable::CREATOR_BUNDLE_NAME, creatorBundleName_); } void ReminderRequest::RecoverActionButtonJsonMode(const std::string &jsonString) { nlohmann::json root = nlohmann::json::parse(jsonString); std::string type = root.at("type").get(); std::string title = root.at("title").get(); std::string resource = root.at("resource").get(); auto buttonWantAgent = std::make_shared(); if (!root["wantAgent"].empty()) { nlohmann::json wantAgent = root["wantAgent"]; buttonWantAgent->pkgName = wantAgent.at("pkgName").get(); buttonWantAgent->abilityName = wantAgent.at("abilityName").get(); } auto buttonDataShareUpdate = std::make_shared(); if (!root["dataShareUpdate"].empty()) { nlohmann::json dataShareUpdate = root["dataShareUpdate"]; buttonDataShareUpdate->uri = dataShareUpdate.at("uri").get(); buttonDataShareUpdate->equalTo = dataShareUpdate.at("equalTo").get(); buttonDataShareUpdate->valuesBucket = dataShareUpdate.at("valuesBucket").get(); } SetActionButton(title, ActionButtonType(std::stoi(type, nullptr)), resource, buttonWantAgent, buttonDataShareUpdate); } void ReminderRequest::RecoverActionButton(const std::shared_ptr &resultSet) { if (resultSet == nullptr) { ANSR_LOGE("ResultSet is null"); return; } std::string actionButtonInfo; ReminderStore::GetStringVal(resultSet, ReminderTable::ACTION_BUTTON_INFO, actionButtonInfo); std::vector multiButton = StringSplit(actionButtonInfo, SEP_BUTTON_MULTI); for (auto button : multiButton) { std::vector singleButton = StringSplit(button, SEP_BUTTON_SINGLE); if (singleButton.size() <= SINGLE_BUTTON_INVALID) { ANSR_LOGW("RecoverButton fail"); return; } if (singleButton.size() == SINGLE_BUTTON_ONLY_ONE) { std::string jsonString = singleButton.at(SINGLE_BUTTON_JSONSTRING); RecoverActionButtonJsonMode(jsonString); continue; } // old method Soon to be deleted if (singleButton.size() < SINGLE_BUTTON_MIN_LEN) { ANSR_LOGW("RecoverButton fail"); return; } auto buttonWantAgent = std::make_shared(); if (singleButton.size() == SINGLE_BUTTON_MAX_LEN) { buttonWantAgent->pkgName = singleButton.at(BUTTON_PKG_INDEX); buttonWantAgent->abilityName = singleButton.at(BUTTON_ABILITY_INDEX); } std::string resource = ""; auto buttonDataShareUpdate = std::make_shared(); SetActionButton(singleButton.at(BUTTON_TITLE_INDEX), ActionButtonType(std::atoi(singleButton.at(BUTTON_TYPE_INDEX).c_str())), resource, buttonWantAgent, buttonDataShareUpdate); ANSR_LOGI("RecoverButton title:%{public}s, pkgName:%{public}s, abilityName:%{public}s", singleButton.at(BUTTON_TITLE_INDEX).c_str(), buttonWantAgent->pkgName.c_str(), buttonWantAgent->abilityName.c_str()); } } std::vector ReminderRequest::StringSplit(std::string source, const std::string &split) { std::vector result; if (source.empty()) { return result; } size_t pos = 0; while ((pos = source.find(split)) != std::string::npos) { std::string token = source.substr(0, pos); if (!token.empty()) { result.push_back(token); } source.erase(0, pos + split.length()); } if (!source.empty()) { result.push_back(source); } return result; } void ReminderRequest::RecoverWantAgent(const std::string &wantAgentInfo, const uint8_t &type) { std::vector info = StringSplit(wantAgentInfo, ReminderRequest::SEP_WANT_AGENT); uint8_t minLen = 2; if (info.size() < minLen) { ANSR_LOGW("RecoverWantAgent fail"); return; } ANSR_LOGD("pkg=%{public}s, ability=%{public}s", info.at(0).c_str(), info.at(1).c_str()); switch (type) { case 0: { auto wai = std::make_shared(); wai->pkgName = info.at(0); wai->abilityName = info.at(1); if (info.size() > minLen) { wai->uri = info.at(WANT_AGENT_URI_INDEX); } SetWantAgentInfo(wai); break; } case 1: { auto maxScreenWantAgentInfo = std::make_shared(); maxScreenWantAgentInfo->pkgName = info.at(0); maxScreenWantAgentInfo->abilityName = info.at(1); SetMaxScreenWantAgentInfo(maxScreenWantAgentInfo); break; } default: { ANSR_LOGW("RecoverWantAgent type not support"); break; } } } ReminderRequest& ReminderRequest::SetMaxScreenWantAgentInfo( const std::shared_ptr &maxScreenWantAgentInfo) { maxScreenWantAgentInfo_ = maxScreenWantAgentInfo; return *this; } ReminderRequest& ReminderRequest::SetNotificationId(int32_t notificationId) { notificationId_ = notificationId; return *this; } ReminderRequest& ReminderRequest::SetGroupId(const std::string &groupId) { groupId_ = groupId; return *this; } ReminderRequest& ReminderRequest::SetSlotType(const NotificationConstant::SlotType &slotType) { slotType_ = slotType; return *this; } ReminderRequest& ReminderRequest::SetSnoozeSlotType(const NotificationConstant::SlotType &snoozeSlotType) { snoozeSlotType_ = snoozeSlotType; 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 > (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}" PRIu64 "<%{public}u", MIN_TIME_INTERVAL_IN_MILLI / MILLI_SECONDS, 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; return *this; } void ReminderRequest::SetTriggerTimeInMilli(uint64_t triggerTimeInMilli) { triggerTimeInMilli_ = triggerTimeInMilli; } ReminderRequest& ReminderRequest::SetWantAgentInfo(const std::shared_ptr &wantAgentInfo) { wantAgentInfo_ = wantAgentInfo; return *this; } 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_; } std::string ReminderRequest::GetCreatorBundleName() const { return creatorBundleName_; } std::string ReminderRequest::GetContent() const { return content_; } std::string ReminderRequest::GetExpiredContent() const { return expiredContent_; } std::shared_ptr ReminderRequest::GetMaxScreenWantAgentInfo() const { return maxScreenWantAgentInfo_; } int32_t ReminderRequest::GetNotificationId() const { return notificationId_; } std::string ReminderRequest::GetGroupId() const { return groupId_; } sptr ReminderRequest::GetNotificationRequest() const { return notificationRequest_; } 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_; } NotificationConstant::SlotType ReminderRequest::GetSnoozeSlotType() const { return snoozeSlotType_; } 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_; } uint64_t ReminderRequest::GetTriggerTimeInMilli() const { return triggerTimeInMilli_; } int32_t ReminderRequest::GetUserId() const { return userId_; } int32_t ReminderRequest::GetUid() const { return uid_; } std::string ReminderRequest::GetBundleName() const { return bundleName_; } void ReminderRequest::SetSystemApp(bool isSystem) { isSystemApp_ = isSystem; } bool ReminderRequest::IsSystemApp() const { return isSystemApp_; } void ReminderRequest::SetTapDismissed(bool tapDismissed) { tapDismissed_ = tapDismissed; } bool ReminderRequest::IsTapDismissed() const { return tapDismissed_; } void ReminderRequest::SetAutoDeletedTime(int64_t autoDeletedTime) { autoDeletedTime_ = autoDeletedTime; } int64_t ReminderRequest::GetAutoDeletedTime() const { return autoDeletedTime_; } void ReminderRequest::SetCustomButtonUri(const std::string &uri) { customButtonUri_ = uri; } std::string ReminderRequest::GetCustomButtonUri() const { return customButtonUri_; } void ReminderRequest::SetCustomRingUri(const std::string &uri) { customRingUri_ = uri; } std::string ReminderRequest::GetCustomRingUri() const { return customRingUri_; } std::shared_ptr ReminderRequest::GetWantAgentInfo() const { return wantAgentInfo_; } ReminderRequest::ReminderType ReminderRequest::GetReminderType() const { return reminderType_; } uint16_t ReminderRequest::GetRingDuration() const { return ringDurationInMilli_ / MILLI_SECONDS; } bool ReminderRequest::UpdateNextReminder() { return false; } bool ReminderRequest::SetNextTriggerTime() { return false; } void ReminderRequest::UpdateNotificationRequest(UpdateNotificationType type, std::string extra) { switch (type) { case UpdateNotificationType::COMMON: { ANSR_LOGI("UpdateNotification common information"); if (extra == "snooze") { UpdateNotificationCommon(true); } else { UpdateNotificationCommon(false); } 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::BUNDLE_INFO: { ANSR_LOGI("UpdateNotification hap information"); UpdateNotificationBundleInfo(); break; } case UpdateNotificationType::CONTENT: { break; } default: break; } } bool ReminderRequest::MarshallingActionButton(Parcel& parcel) const { // write map uint64_t actionButtonMapSize = static_cast(actionButtonMap_.size()); WRITE_UINT64_RETURN_FALSE_LOG(parcel, actionButtonMapSize, "actionButtonMapSize"); for (auto button : actionButtonMap_) { uint8_t buttonType = static_cast(button.first); WRITE_UINT8_RETURN_FALSE_LOG(parcel, buttonType, "buttonType"); WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.title, "buttonTitle"); WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.resource, "buttonResource"); if (button.second.wantAgent == nullptr) { ANSR_LOGE("button wantAgent is null"); return false; } WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.wantAgent->pkgName, "wantAgent's pkgName"); WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.wantAgent->abilityName, "wantAgent's abilityName"); if (button.second.dataShareUpdate == nullptr) { ANSR_LOGE("button dataShareUpdate is null"); return false; } WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.dataShareUpdate->uri, "dataShareUpdate's uri"); WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.dataShareUpdate->equalTo, "dataShareUpdate's equalTo"); WRITE_STRING_RETURN_FALSE_LOG(parcel, button.second.dataShareUpdate->valuesBucket, "dataShareUpdate's valuesBucket"); } return true; } bool ReminderRequest::Marshalling(Parcel &parcel) const { // write string WRITE_STRING_RETURN_FALSE_LOG(parcel, content_, "content"); WRITE_STRING_RETURN_FALSE_LOG(parcel, expiredContent_, "expiredContent"); WRITE_STRING_RETURN_FALSE_LOG(parcel, snoozeContent_, "snoozeContent"); WRITE_STRING_RETURN_FALSE_LOG(parcel, title_, "title"); WRITE_STRING_RETURN_FALSE_LOG(parcel, wantAgentInfo_->abilityName, "wantAgentInfo's abilityName"); WRITE_STRING_RETURN_FALSE_LOG(parcel, wantAgentInfo_->pkgName, "wantAgentInfo's pkgName"); WRITE_STRING_RETURN_FALSE_LOG(parcel, wantAgentInfo_->uri, "wantAgentInfo's uri"); WRITE_STRING_RETURN_FALSE_LOG(parcel, maxScreenWantAgentInfo_->abilityName, "maxScreenWantAgentInfo's abilityName"); WRITE_STRING_RETURN_FALSE_LOG(parcel, maxScreenWantAgentInfo_->pkgName, "maxScreenWantAgentInfo's pkgName"); WRITE_STRING_RETURN_FALSE_LOG(parcel, customButtonUri_, "customButtonUri"); WRITE_STRING_RETURN_FALSE_LOG(parcel, customRingUri_, "customRingUri"); WRITE_STRING_RETURN_FALSE_LOG(parcel, creatorBundleName_, "creatorBundleName"); // write bool WRITE_BOOL_RETURN_FALSE_LOG(parcel, isExpired_, "isExpired"); WRITE_BOOL_RETURN_FALSE_LOG(parcel, isSystemApp_, "isSystemApp"); WRITE_BOOL_RETURN_FALSE_LOG(parcel, tapDismissed_, "tapDismissed"); // write int WRITE_INT64_RETURN_FALSE_LOG(parcel, autoDeletedTime_, "autoDeletedTime"); WRITE_INT32_RETURN_FALSE_LOG(parcel, reminderId_, "reminderId"); WRITE_INT32_RETURN_FALSE_LOG(parcel, notificationId_, "notificationId"); WRITE_STRING_RETURN_FALSE_LOG(parcel, groupId_, "groupId"); WRITE_UINT64_RETURN_FALSE_LOG(parcel, triggerTimeInMilli_, "triggerTimeInMilli"); WRITE_UINT64_RETURN_FALSE_LOG(parcel, timeIntervalInMilli_, "timeIntervalInMilli"); WRITE_UINT64_RETURN_FALSE_LOG(parcel, ringDurationInMilli_, "ringDurationInMilli"); WRITE_UINT64_RETURN_FALSE_LOG(parcel, reminderTimeInMilli_, "reminderTimeInMilli"); WRITE_UINT8_RETURN_FALSE_LOG(parcel, snoozeTimes_, "snoozeTimes"); WRITE_UINT8_RETURN_FALSE_LOG(parcel, snoozeTimesDynamic_, "snoozeTimesDynamic"); WRITE_UINT8_RETURN_FALSE_LOG(parcel, state_, "state"); WRITE_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek"); // write enum uint8_t reminderType = static_cast(reminderType_); WRITE_UINT8_RETURN_FALSE_LOG(parcel, reminderType, "reminderType"); int32_t slotType = static_cast(slotType_); WRITE_INT32_RETURN_FALSE_LOG(parcel, slotType, "slotType"); int32_t snoozeSlotType = static_cast(snoozeSlotType_); WRITE_INT32_RETURN_FALSE_LOG(parcel, snoozeSlotType, "snoozeSlotType"); if (!MarshallingActionButton(parcel)) { return false; } return true; } ReminderRequest *ReminderRequest::Unmarshalling(Parcel &parcel) { auto objptr = new (std::nothrow) ReminderRequest(); if (objptr == nullptr) { ANSR_LOGE("Failed to create reminder due to no memory."); return objptr; } if (!objptr->ReadFromParcel(parcel)) { delete objptr; objptr = nullptr; } return objptr; } bool ReminderRequest::ReadActionButtonFromParcel(Parcel& parcel) { uint64_t buttonMapSize = 0; READ_UINT64_RETURN_FALSE_LOG(parcel, buttonMapSize, "actionButtonMapSize"); buttonMapSize = (buttonMapSize < MAX_ACTION_BUTTON_NUM) ? buttonMapSize : MAX_ACTION_BUTTON_NUM; for (uint64_t i = 0; i < buttonMapSize; i++) { uint8_t buttonType = static_cast(ActionButtonType::INVALID); READ_UINT8_RETURN_FALSE_LOG(parcel, buttonType, "buttonType"); ActionButtonType type = static_cast(buttonType); std::string title = parcel.ReadString(); std::string resource = parcel.ReadString(); std::string pkgName = parcel.ReadString(); std::string abilityName = parcel.ReadString(); std::string uri = parcel.ReadString(); std::string equalTo = parcel.ReadString(); std::string valuesBucket = parcel.ReadString(); ActionButtonInfo info; info.type = type; info.title = title; info.resource = resource; info.wantAgent = std::make_shared(); if (info.wantAgent == nullptr) { return false; } info.wantAgent->pkgName = pkgName; info.wantAgent->abilityName = abilityName; info.dataShareUpdate = std::make_shared(); if (info.dataShareUpdate == nullptr) { return false; } info.dataShareUpdate->uri = uri; info.dataShareUpdate->equalTo = equalTo; info.dataShareUpdate->valuesBucket = valuesBucket; actionButtonMap_.insert(std::pair(type, info)); } return true; } bool ReminderRequest::ReadFromParcel(Parcel &parcel) { READ_STRING_RETURN_FALSE_LOG(parcel, content_, "content"); READ_STRING_RETURN_FALSE_LOG(parcel, expiredContent_, "expiredContent"); READ_STRING_RETURN_FALSE_LOG(parcel, snoozeContent_, "snoozeContent"); READ_STRING_RETURN_FALSE_LOG(parcel, title_, "title"); READ_STRING_RETURN_FALSE_LOG(parcel, wantAgentInfo_->abilityName, "wantAgentInfo's abilityName"); READ_STRING_RETURN_FALSE_LOG(parcel, wantAgentInfo_->pkgName, "wantAgentInfo's pkgName"); READ_STRING_RETURN_FALSE_LOG(parcel, wantAgentInfo_->uri, "wantAgentInfo's uri"); READ_STRING_RETURN_FALSE_LOG(parcel, maxScreenWantAgentInfo_->abilityName, "maxScreenWantAgentInfo's abilityName"); READ_STRING_RETURN_FALSE_LOG(parcel, maxScreenWantAgentInfo_->pkgName, "maxScreenWantAgentInfo's pkgName"); READ_STRING_RETURN_FALSE_LOG(parcel, customButtonUri_, "customButtonUri"); READ_STRING_RETURN_FALSE_LOG(parcel, customRingUri_, "customRingUri"); READ_STRING_RETURN_FALSE_LOG(parcel, creatorBundleName_, "creatorBundleName"); READ_BOOL_RETURN_FALSE_LOG(parcel, isExpired_, "isExpired"); READ_BOOL_RETURN_FALSE_LOG(parcel, isSystemApp_, "isSystemApp"); READ_BOOL_RETURN_FALSE_LOG(parcel, tapDismissed_, "tapDismissed"); READ_INT64_RETURN_FALSE_LOG(parcel, autoDeletedTime_, "autoDeletedTime"); int32_t tempReminderId = -1; READ_INT32_RETURN_FALSE_LOG(parcel, tempReminderId, "reminderId"); reminderId_ = (tempReminderId == -1) ? reminderId_ : tempReminderId; READ_INT32_RETURN_FALSE_LOG(parcel, notificationId_, "notificationId"); READ_STRING_RETURN_FALSE_LOG(parcel, groupId_, "groupId"); READ_UINT64_RETURN_FALSE_LOG(parcel, triggerTimeInMilli_, "triggerTimeInMilli"); READ_UINT64_RETURN_FALSE_LOG(parcel, timeIntervalInMilli_, "timeIntervalInMilli"); READ_UINT64_RETURN_FALSE_LOG(parcel, ringDurationInMilli_, "ringDurationInMilli"); READ_UINT64_RETURN_FALSE_LOG(parcel, reminderTimeInMilli_, "reminderTimeInMilli"); READ_UINT8_RETURN_FALSE_LOG(parcel, snoozeTimes_, "snoozeTimes"); READ_UINT8_RETURN_FALSE_LOG(parcel, snoozeTimesDynamic_, "snoozeTimesDynamic"); READ_UINT8_RETURN_FALSE_LOG(parcel, state_, "state"); READ_UINT8_RETURN_FALSE_LOG(parcel, repeatDaysOfWeek_, "repeatDaysOfWeek"); uint8_t reminderType = static_cast(ReminderType::INVALID); READ_UINT8_RETURN_FALSE_LOG(parcel, reminderType, "reminderType"); reminderType_ = static_cast(reminderType); int32_t slotType = static_cast(NotificationConstant::SlotType::OTHER); READ_INT32_RETURN_FALSE_LOG(parcel, slotType, "slotType"); slotType_ = static_cast(slotType); int32_t snoozeSlotType = static_cast(NotificationConstant::SlotType::OTHER); READ_INT32_RETURN_FALSE_LOG(parcel, snoozeSlotType, "snoozeSlotType"); snoozeSlotType_ = static_cast(snoozeSlotType); if (!ReadActionButtonFromParcel(parcel)) { return false; } if (!InitNotificationRequest()) { return false; } return true; } bool ReminderRequest::InitNotificationRequest() { ANSR_LOGI("Init notification"); notificationRequest_ = new (std::nothrow) NotificationRequest(notificationId_); if (notificationRequest_ == nullptr) { ANSR_LOGE("Failed to create notification."); return false; } displayContent_ = content_; AddActionButtons(true); return true; } void ReminderRequest::InitServerObj() { wantAgentInfo_ = wantAgentInfo_ == nullptr ? std::make_shared() : wantAgentInfo_; maxScreenWantAgentInfo_ = maxScreenWantAgentInfo_ == nullptr ? std::make_shared() : maxScreenWantAgentInfo_; } bool ReminderRequest::IsAlerting() const { return (state_ & REMINDER_STATUS_ALERTING) != 0; } uint64_t ReminderRequest::GetDurationSinceEpochInMilli(const time_t target) { auto tarEndTimePoint = std::chrono::system_clock::from_time_t(target); auto tarDuration = std::chrono::duration_cast(tarEndTimePoint.time_since_epoch()); int64_t tarDate = tarDuration.count(); if (tarDate < 0) { ANSR_LOGW("tarDuration is less than 0."); return INVALID_LONG_LONG_VALUE; } return static_cast(tarDate); } std::string ReminderRequest::GetDateTimeInfo(const time_t &timeInSecond) const { return GetTimeInfoInner(timeInSecond, TimeFormat::YMDHMS, true); } std::string ReminderRequest::GetButtonInfo() const { std::string info = ""; bool isFirst = true; for (auto button : actionButtonMap_) { if (!isFirst) { info += SEP_BUTTON_MULTI; } ActionButtonInfo buttonInfo = button.second; nlohmann::json root; root["type"] = std::to_string(static_cast(button.first)); root["title"] = buttonInfo.title; root["resource"] = buttonInfo.resource; if (buttonInfo.wantAgent != nullptr) { nlohmann::json wantAgentfriends; wantAgentfriends["pkgName"] = buttonInfo.wantAgent->pkgName; wantAgentfriends["abilityName"] = buttonInfo.wantAgent->abilityName; root["wantAgent"] = wantAgentfriends; } if (buttonInfo.dataShareUpdate != nullptr) { nlohmann::json dataShareUpdatefriends; dataShareUpdatefriends["uri"] = buttonInfo.dataShareUpdate->uri; dataShareUpdatefriends["equalTo"] = buttonInfo.dataShareUpdate->equalTo; dataShareUpdatefriends["valuesBucket"] = buttonInfo.dataShareUpdate->valuesBucket; root["dataShareUpdate"] = dataShareUpdatefriends; } std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace); info += str; isFirst = false; } return info; } uint64_t ReminderRequest::GetNowInstantMilli() const { time_t now; (void)time(&now); // unit is seconds. if (static_cast(now) < 0) { ANSR_LOGE("Get now time error"); return 0; } return GetDurationSinceEpochInMilli(now); } std::string ReminderRequest::GetShowTime(const uint64_t showTime) const { if (reminderType_ == ReminderType::TIMER) { return ""; } return GetTimeInfoInner(static_cast(showTime / MILLI_SECONDS), TimeFormat::HM, false); } std::string ReminderRequest::GetTimeInfoInner(const time_t &timeInSecond, const TimeFormat &format, bool keep24Hour) const { const uint8_t dateTimeLen = 80; char dateTimeBuffer[dateTimeLen]; struct tm timeInfo; (void)localtime_r(&timeInSecond, &timeInfo); bool is24HourClock = OHOS::Global::I18n::LocaleConfig::Is24HourClock(); if (!is24HourClock && timeInfo.tm_hour > TIME_HOUR_OFFSET && !keep24Hour) { timeInfo.tm_hour -= TIME_HOUR_OFFSET; } switch (format) { case TimeFormat::YMDHMS: { (void)strftime(dateTimeBuffer, dateTimeLen, "%Y-%m-%d %H:%M:%S", &timeInfo); break; } case TimeFormat::HM: { (void)strftime(dateTimeBuffer, dateTimeLen, "%H:%M", &timeInfo); break; } default: { ANSR_LOGW("Time format not support."); break; } } std::string dateTimeInfo(dateTimeBuffer); return dateTimeInfo; } std::string ReminderRequest::GetState(const uint8_t state) const { std::string stateInfo = "'"; if (state == REMINDER_STATUS_INACTIVE) { 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) { if (hasSeparator) { stateInfo += ","; } stateInfo += "Showing"; hasSeparator = true; } if ((state & REMINDER_STATUS_SNOOZE) != 0) { if (hasSeparator) { stateInfo += ","; } stateInfo += "Snooze"; } } stateInfo += "'"; return stateInfo; } void ReminderRequest::AddActionButtons(const bool includeSnooze) { int32_t requestCode = 10; std::vector flags; flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); for (auto button : actionButtonMap_) { auto want = std::make_shared(); auto type = button.first; switch (type) { case ActionButtonType::CLOSE: want->SetAction(REMINDER_EVENT_CLOSE_ALERT); break; case ActionButtonType::SNOOZE: if (includeSnooze) { want->SetAction(REMINDER_EVENT_SNOOZE_ALERT); } else { ANSR_LOGD("Not add action button, type is snooze, as includeSnooze is false"); continue; } break; case ActionButtonType::CUSTOM: want->SetAction(REMINDER_EVENT_CUSTOM_ALERT); if (button.second.wantAgent == nullptr) { return; } want->SetParam("PkgName", button.second.wantAgent->pkgName); want->SetParam("AbilityName", button.second.wantAgent->abilityName); break; default: break; } want->SetParam(PARAM_REMINDER_ID, reminderId_); std::vector> wants; wants.push_back(want); auto title = static_cast(button.second.title); AbilityRuntime::WantAgent::WantAgentInfo buttonWantAgentInfo( requestCode, AbilityRuntime::WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT, flags, wants, nullptr ); std::string identity = IPCSkeleton::ResetCallingIdentity(); std::shared_ptr buttonWantAgent = AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(buttonWantAgentInfo, userId_); IPCSkeleton::SetCallingIdentity(identity); std::shared_ptr actionButton = NotificationActionButton::Create(nullptr, title, buttonWantAgent); notificationRequest_->AddActionButton(actionButton); } } void ReminderRequest::AddRemovalWantAgent() { int32_t requestCode = 10; std::vector flags; flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); auto want = std::make_shared(); want->SetAction(REMINDER_EVENT_REMOVE_NOTIFICATION); want->SetParam(PARAM_REMINDER_ID, reminderId_); std::vector> wants; wants.push_back(want); AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo( requestCode, AbilityRuntime::WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT, flags, wants, nullptr ); std::string identity = IPCSkeleton::ResetCallingIdentity(); std::shared_ptr wantAgent = AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo, userId_); IPCSkeleton::SetCallingIdentity(identity); notificationRequest_->SetRemovalWantAgent(wantAgent); } std::shared_ptr ReminderRequest::CreateWantAgent( AppExecFwk::ElementName &element, bool isWantAgent) const { int32_t requestCode = 10; std::vector flags; flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); auto want = std::make_shared(); want->SetElement(element); if (isWantAgent) { want->SetUri(wantAgentInfo_->uri); } std::vector> wants; wants.push_back(want); AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo( requestCode, AbilityRuntime::WantAgent::WantAgentConstant::OperationType::START_ABILITY, flags, wants, nullptr ); std::string identity = IPCSkeleton::ResetCallingIdentity(); auto wantAgent = AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo, userId_); IPCSkeleton::SetCallingIdentity(identity); return wantAgent; } void ReminderRequest::SetMaxScreenWantAgent(AppExecFwk::ElementName &element) { std::shared_ptr wantAgent = CreateWantAgent(element, false); notificationRequest_->SetMaxScreenWantAgent(wantAgent); } void ReminderRequest::SetWantAgent(AppExecFwk::ElementName &element) { std::shared_ptr wantAgent = CreateWantAgent(element, true); notificationRequest_->SetWantAgent(wantAgent); } void ReminderRequest::SetState(bool deSet, const uint8_t newState, std::string function) { uint8_t oldState = state_; if (deSet) { state_ |= newState; } else { state_ &= static_cast(~newState); } 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::SetStateToInActive() { SetState(false, (REMINDER_STATUS_SHOWING | REMINDER_STATUS_ALERTING | REMINDER_STATUS_ACTIVE), "SetStateToInActive"); } void ReminderRequest::UpdateActionButtons(const bool &setSnooze) { if (notificationRequest_ == nullptr) { ANSR_LOGE("updateActionButtons failed, the notificationRequest is null"); return; } notificationRequest_->ClearActionButtons(); if (setSnooze) { 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 ? "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(bool isSnooze) { time_t now; (void)time(&now); // unit is seconds. notificationRequest_->SetDeliveryTime(GetDurationSinceEpochInMilli(now)); notificationRequest_->SetLabel(NOTIFICATION_LABEL); notificationRequest_->SetShowDeliveryTime(true); if (isSnooze) { if (snoozeSlotType_ == NotificationConstant::SlotType::OTHER) { notificationRequest_->SetSlotType(NotificationConstant::SlotType::CONTENT_INFORMATION); } else { notificationRequest_->SetSlotType(snoozeSlotType_); } } else { notificationRequest_->SetSlotType(slotType_); } notificationRequest_->SetTapDismissed(tapDismissed_); notificationRequest_->SetAutoDeletedTime(autoDeletedTime_); 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); } } void ReminderRequest::UpdateNotificationBundleInfo() { std::string ownerBundleName = notificationRequest_->GetOwnerBundleName(); if (!(ownerBundleName.empty())) { return; } ANSR_LOGD("ownerBundleName=%{public}s, bundleName_=%{public}s", ownerBundleName.c_str(), bundleName_.c_str()); notificationRequest_->SetOwnerBundleName(bundleName_); notificationRequest_->SetCreatorBundleName(bundleName_); notificationRequest_->SetCreatorUid(uid_); ErrCode errCode = AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid_, userId_); if (errCode != ERR_OK) { ANSR_LOGE("GetOsAccountLocalIdFromUid fail."); return; } notificationRequest_->SetCreatorUserId(userId_); } 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 = snoozeContent_; notificationRequest_->SetTapDismissed(false); } else { // the reminder is expired now, when timeInterval is 0 extendContent = expiredContent_; } } else if (IsAlerting()) { // the reminder is alerting, or ring duration is 0 extendContent = ""; } else if (snoozeTimesDynamic_ != snoozeTimes_) { // the reminder is snoozing by period artithmetic, when the ring duration is over. extendContent = snoozeContent_; notificationRequest_->SetTapDismissed(false); } else { // the reminder has already snoozed by period arithmetic, when the ring duration is over. extendContent = expiredContent_; } if (extendContent == "") { displayContent_ = content_; } else { displayContent_ = extendContent; } ANSR_LOGD("Display content=%{public}s", displayContent_.c_str()); } void ReminderRequest::UpdateNotificationStateForAlert() { ANSR_LOGD("UpdateNotification content and buttons"); UpdateNotificationContent(false); UpdateActionButtons(false); } void ReminderRequest::UpdateNotificationStateForSnooze() { ANSR_LOGD("UpdateNotification content and buttons"); UpdateNotificationContent(true); UpdateActionButtons(true); } int32_t ReminderRequest::GetActualTime(const TimeTransferType &type, int32_t cTime) { switch (type) { case (TimeTransferType::YEAR): // year return BASE_YEAR + cTime; case (TimeTransferType::MONTH): // month return 1 + cTime; case (TimeTransferType::WEEK): { // week return cTime == 0 ? SUNDAY : cTime; } default: return -1; } } int32_t ReminderRequest::GetCTime(const TimeTransferType &type, int32_t actualTime) { switch (type) { case (TimeTransferType::YEAR): // year return actualTime - BASE_YEAR; case (TimeTransferType::MONTH): // month return actualTime - 1; case (TimeTransferType::WEEK): { // week return actualTime == SUNDAY ? 0 : actualTime; } default: return -1; } } int32_t ReminderRequest::GetUid(const int32_t &userId, const std::string &bundleName) { AppExecFwk::ApplicationInfo info; sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (systemAbilityManager == nullptr) { ANSR_LOGE("Failed to get uid due to get systemAbilityManager is null."); return -1; } sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); if (remoteObject == nullptr) { ANSR_LOGE("Fail to get bundle manager proxy"); return -1; } sptr bundleMgr = iface_cast(remoteObject); if (bundleMgr == nullptr) { ANSR_LOGE("Bundle mgr proxy is nullptr"); return -1; } bundleMgr->GetApplicationInfo(bundleName, AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, info); ANSR_LOGD("uid=%{public}d", info.uid); return static_cast(info.uid); } int32_t ReminderRequest::GetUserId(const int32_t &uid) { int32_t userId = -1; AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid, userId); ANSR_LOGD("userId=%{public}d", userId); return userId; } void ReminderRequest::AppendWantAgentValuesBucket(const sptr& reminder, NativeRdb::ValuesBucket& values) { auto wantAgentInfo = reminder->GetWantAgentInfo(); if (wantAgentInfo == nullptr) { std::string info = "null" + ReminderRequest::SEP_WANT_AGENT + "null" + ReminderRequest::SEP_WANT_AGENT + "null"; values.PutString(ReminderTable::AGENT, info); } else { std::string info = wantAgentInfo->pkgName + ReminderRequest::SEP_WANT_AGENT + wantAgentInfo->abilityName + ReminderRequest::SEP_WANT_AGENT + wantAgentInfo->uri; values.PutString(ReminderTable::AGENT, info); } auto maxScreenWantAgentInfo = reminder->GetMaxScreenWantAgentInfo(); if (maxScreenWantAgentInfo == nullptr) { std::string info = "null" + ReminderRequest::SEP_WANT_AGENT + "null"; values.PutString(ReminderTable::MAX_SCREEN_AGENT, info); } else { values.PutString(ReminderTable::MAX_SCREEN_AGENT, maxScreenWantAgentInfo->pkgName + ReminderRequest::SEP_WANT_AGENT + maxScreenWantAgentInfo->abilityName); } } void ReminderRequest::AppendValuesBucket(const sptr &reminder, const sptr &bundleOption, NativeRdb::ValuesBucket &values) { values.PutInt(ReminderTable::REMINDER_ID, reminder->GetReminderId()); values.PutString(ReminderTable::PKG_NAME, bundleOption->GetBundleName()); values.PutInt(ReminderTable::USER_ID, reminder->GetUserId()); values.PutInt(ReminderTable::UID, reminder->GetUid()); values.PutString(ReminderTable::SYS_APP, reminder->IsSystemApp() ? "true" : "false"); values.PutString(ReminderTable::APP_LABEL, ""); // no use, compatible with old version. values.PutInt(ReminderTable::REMINDER_TYPE, static_cast(reminder->GetReminderType())); values.PutLong(ReminderTable::REMINDER_TIME, reminder->GetReminderTimeInMilli()); values.PutLong(ReminderTable::TRIGGER_TIME, reminder->GetTriggerTimeInMilli()); values.PutLong( ReminderTable::RTC_TRIGGER_TIME, reminder->GetTriggerTimeInMilli()); // no use, compatible with old version. values.PutLong(ReminderTable::TIME_INTERVAL, reminder->GetTimeInterval()); values.PutInt(ReminderTable::SNOOZE_TIMES, reminder->GetSnoozeTimes()); values.PutInt(ReminderTable::DYNAMIC_SNOOZE_TIMES, reminder->GetSnoozeTimesDynamic()); values.PutLong(ReminderTable::RING_DURATION, reminder->GetRingDuration()); values.PutString(ReminderTable::IS_EXPIRED, reminder->IsExpired() ? "true" : "false"); values.PutString(ReminderTable::IS_ACTIVE, ""); // no use, compatible with old version. values.PutInt(ReminderTable::STATE, reminder->GetState()); values.PutString(ReminderTable::ZONE_ID, ""); // no use, compatible with old version. values.PutString(ReminderTable::HAS_SCHEDULED_TIMEOUT, ""); // no use, compatible with old version. values.PutString(ReminderTable::ACTION_BUTTON_INFO, reminder->GetButtonInfo()); values.PutString(ReminderTable::CUSTOM_BUTTON_URI, reminder->GetCustomButtonUri()); values.PutInt(ReminderTable::SLOT_ID, reminder->GetSlotType()); values.PutInt(ReminderTable::SNOOZE_SLOT_ID, reminder->GetSnoozeSlotType()); values.PutInt(ReminderTable::NOTIFICATION_ID, reminder->GetNotificationId()); values.PutString(ReminderTable::TITLE, reminder->GetTitle()); values.PutString(ReminderTable::CONTENT, reminder->GetContent()); values.PutString(ReminderTable::SNOOZE_CONTENT, reminder->GetSnoozeContent()); values.PutString(ReminderTable::EXPIRED_CONTENT, reminder->GetExpiredContent()); values.PutInt(ReminderTable::REPEAT_DAYS_OF_WEEK, reminder->GetRepeatDaysOfWeek()); values.PutString(ReminderTable::GROUP_ID, reminder->GetGroupId()); values.PutString(ReminderTable::CUSTOM_RING_URI, reminder->GetCustomRingUri()); values.PutString(ReminderTable::CREATOR_BUNDLE_NAME, reminder->GetCreatorBundleName()); AppendWantAgentValuesBucket(reminder, values); values.PutString(ReminderTable::TAP_DISMISSED, reminder->IsTapDismissed() ? "true" : "false"); values.PutLong(ReminderTable::AUTO_DELETED_TIME, reminder->GetAutoDeletedTime()); } int64_t ReminderRequest::GetNextDaysOfWeek(const time_t now, const time_t target) const { struct tm nowTime; (void)localtime_r(&now, &nowTime); int32_t today = GetActualTime(TimeTransferType::WEEK, nowTime.tm_wday); int32_t dayCount = now >= target ? 1 : 0; for (; dayCount <= DAYS_PER_WEEK; dayCount++) { int32_t day = (today + dayCount) % DAYS_PER_WEEK; day = (day == 0) ? SUNDAY : day; if (IsRepeatDaysOfWeek(day)) { break; } } ANSR_LOGI("NextDayInterval is %{public}d", dayCount); time_t nextTriggerTime = target + dayCount * HOURS_PER_DAY * SECONDS_PER_HOUR; return GetTriggerTime(now, nextTriggerTime); } bool ReminderRequest::IsRepeatDaysOfWeek(int32_t day) const { return (repeatDaysOfWeek_ & (1 << (day - 1))) > 0; } time_t ReminderRequest::GetTriggerTimeWithDST(const time_t now, const time_t nextTriggerTime) const { time_t triggerTime = nextTriggerTime; struct tm nowLocal; struct tm nextLocal; (void)localtime_r(&now, &nowLocal); (void)localtime_r(&nextTriggerTime, &nextLocal); if (nowLocal.tm_isdst == 0 && nextLocal.tm_isdst > 0) { triggerTime -= SECONDS_PER_HOUR; } else if (nowLocal.tm_isdst > 0 && nextLocal.tm_isdst == 0) { triggerTime += SECONDS_PER_HOUR; } return triggerTime; } uint8_t ReminderRequest::GetRepeatDaysOfWeek() const { return repeatDaysOfWeek_; } void ReminderRequest::SetRepeatDaysOfWeek(bool set, const std::vector &daysOfWeek) { if (daysOfWeek.size() == 0) { return; } if (daysOfWeek.size() > DAYS_PER_WEEK) { ANSR_LOGE("The length of daysOfWeek should not larger than 7"); return; } for (auto it = daysOfWeek.begin(); it != daysOfWeek.end(); ++it) { if (*it < MONDAY || *it > SUNDAY) { continue; } if (set) { repeatDaysOfWeek_ |= 1 << (*it - 1); } else { repeatDaysOfWeek_ &= ~(1 << (*it - 1)); } } } std::vector ReminderRequest::GetDaysOfWeek() const { std::vector repeatDays; int32_t days[] = {1, 2, 3, 4, 5, 6, 7}; int32_t len = sizeof(days) / sizeof(int32_t); for (int32_t i = 0; i < len; i++) { if (IsRepeatDaysOfWeek(days[i])) { repeatDays.push_back(days[i]); } } return repeatDays; } uint64_t ReminderRequest::GetTriggerTime(const time_t now, const time_t nextTriggerTime) const { time_t triggerTime = GetTriggerTimeWithDST(now, nextTriggerTime); struct tm test; (void)localtime_r(&triggerTime, &test); 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", 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)triggerTime); if (static_cast(triggerTime) <= 0) { return 0; } return GetDurationSinceEpochInMilli(triggerTime); } void ReminderRequest::OnLanguageChange(const std::shared_ptr &resMgr) { if (resMgr == nullptr) { return; } // update title for (auto &button : actionButtonMap_) { std::string title; resMgr->GetStringByName(button.second.resource.c_str(), title); if (title.empty()) { continue; } button.second.title = title; } // update action button UpdateActionButtons(false); } } }