diff --git a/frameworks/ans/core/BUILD.gn b/frameworks/ans/core/BUILD.gn index e262036dd78de4e5e308074cb3241651f6d55f89..e2ba42989e54c9aee761543abe0a9dd481289008 100644 --- a/frameworks/ans/core/BUILD.gn +++ b/frameworks/ans/core/BUILD.gn @@ -31,6 +31,8 @@ config("public_ans_core_config") { "//utils/native/base/include", "//third_party/jsoncpp/include", ] + + cflags_cc = [ "-fexceptions" ] } ohos_shared_library("ans_core") { @@ -66,6 +68,10 @@ ohos_shared_library("ans_core") { "${frameworks_path}/ans/native/src/notification_subscribe_info.cpp", "${frameworks_path}/ans/native/src/notification_subscriber.cpp", "${frameworks_path}/ans/native/src/notification_user_input.cpp", + "${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_timer.cpp", ] configs = [ ":private_config" ] @@ -74,8 +80,12 @@ ohos_shared_library("ans_core") { deps = [ "${frameworks_path}/wantagent:wantagent_innerkits", + "//base/miscservices/time/services:time_service", "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/kits:appkit_native", "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr:distributedschedsvr", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", "//third_party/jsoncpp:jsoncpp", "//utils/native/base:utils", diff --git a/frameworks/ans/core/common/include/ans_log_wrapper.h b/frameworks/ans/core/common/include/ans_log_wrapper.h index c9543f7ca7733971871baa2e6b0995616984afa5..cbcc8a923dc870f735c88a3c881e91622965cb0e 100644 --- a/frameworks/ans/core/common/include/ans_log_wrapper.h +++ b/frameworks/ans/core/common/include/ans_log_wrapper.h @@ -33,6 +33,7 @@ namespace Notification { enum class AnsLogLevel : uint8_t { DEBUG = 0, INFO, WARN, ERROR, FATAL }; static constexpr OHOS::HiviewDFX::HiLogLabel ANS_LABEL = {LOG_CORE, LOG_DOMAIN, "ANS_STANDARD"}; +static constexpr OHOS::HiviewDFX::HiLogLabel ANS_REMINDER_LABEL = {LOG_CORE, LOG_DOMAIN, "ANS_REMINDER"}; class AnsLogWrapper { public: @@ -71,6 +72,21 @@ private: #define ANS_LOGW(fmt, ...) PRINT_LOG(WARN, Warn, fmt, ##__VA_ARGS__) #define ANS_LOGE(fmt, ...) PRINT_LOG(ERROR, Error, fmt, ##__VA_ARGS__) #define ANS_LOGF(fmt, ...) PRINT_LOG(FATAL, Fatal, fmt, ##__VA_ARGS__) + +#define PRINT_REMINDER_LOG(LEVEL, Level, fmt, ...) \ + if (AnsLogWrapper::JudgeLevel(AnsLogLevel::LEVEL)) \ + OHOS::HiviewDFX::HiLog::Level(ANS_REMINDER_LABEL, \ + "[%{public}s(%{public}s):%{public}d] " fmt, \ + AnsLogWrapper::GetBriefFileName(__FILE__).c_str(), \ + __FUNCTION__, \ + __LINE__, \ + ##__VA_ARGS__) + +#define ANSR_LOGD(fmt, ...) PRINT_REMINDER_LOG(DEBUG, Debug, fmt, ##__VA_ARGS__) +#define ANSR_LOGI(fmt, ...) PRINT_REMINDER_LOG(INFO, Info, fmt, ##__VA_ARGS__) +#define ANSR_LOGW(fmt, ...) PRINT_REMINDER_LOG(WARN, Warn, fmt, ##__VA_ARGS__) +#define ANSR_LOGE(fmt, ...) PRINT_REMINDER_LOG(ERROR, Error, fmt, ##__VA_ARGS__) +#define ANSR_LOGF(fmt, ...) PRINT_REMINDER_LOG(FATAL, Fatal, fmt, ##__VA_ARGS__) } // namespace Notification } // namespace OHOS diff --git a/frameworks/ans/core/include/ans_manager_interface.h b/frameworks/ans/core/include/ans_manager_interface.h index be9a8b105e20a2affa402791a5c9e9c14517009e..9657c2b34ed010cedc43328b5648c2a3ef3a87bd 100644 --- a/frameworks/ans/core/include/ans_manager_interface.h +++ b/frameworks/ans/core/include/ans_manager_interface.h @@ -28,6 +28,7 @@ #include "notification_slot.h" #include "notification_slot_group.h" #include "notification_subscribe_info.h" +#include "reminder_request.h" namespace OHOS { namespace Notification { @@ -113,6 +114,10 @@ public: virtual ErrCode ShellDump(const std::string &dumpOption, std::vector &dumpInfo) = 0; virtual ErrCode PublishContinuousTaskNotification(const sptr &request) = 0; virtual ErrCode CancelContinuousTaskNotification(const std::string &label, int32_t notificationId) = 0; + virtual ErrCode PublishReminder(sptr &reminder) = 0; + virtual ErrCode CancelReminder(const int32_t reminderId) = 0; + virtual ErrCode GetValidReminders(std::vector> &reminders) = 0; + virtual ErrCode CancelAllReminders() = 0; protected: enum TransactId : uint32_t { @@ -172,6 +177,10 @@ protected: SHELL_DUMP, PUBLISH_CONTINUOUS_TASK_NOTIFICATION, CANCEL_CONTINUOUS_TASK_NOTIFICATION, + PUBLISH_REMINDER, + CANCEL_REMINDER, + CANCEL_ALL_REMINDERS, + GET_ALL_VALID_REMINDERS }; }; } // namespace Notification diff --git a/frameworks/ans/core/include/ans_manager_proxy.h b/frameworks/ans/core/include/ans_manager_proxy.h index 77cd702690e590184bc3569e04273c8d8c7a94fe..d5bd993e1897726d320e7ded3c2dc70a0c1b66e6 100644 --- a/frameworks/ans/core/include/ans_manager_proxy.h +++ b/frameworks/ans/core/include/ans_manager_proxy.h @@ -102,6 +102,11 @@ public: ErrCode PublishContinuousTaskNotification(const sptr &request) override; ErrCode CancelContinuousTaskNotification(const std::string &label, int32_t notificationId) override; + ErrCode PublishReminder(sptr &reminder) override; + ErrCode CancelReminder(const int32_t reminderId) override; + ErrCode GetValidReminders(std::vector> &reminders) override; + ErrCode CancelAllReminders() override; + private: ErrCode InnerTransact(uint32_t code, MessageOption &flags, MessageParcel &data, MessageParcel &reply); @@ -111,6 +116,8 @@ private: template bool ReadParcelableVector(std::vector> &parcelableInfos, MessageParcel &reply, ErrCode &result); static inline BrokerDelegator delegator_; + + ErrCode ReadReminders(uint8_t &count, MessageParcel &reply, std::vector> &reminders); }; } // namespace Notification } // namespace OHOS diff --git a/frameworks/ans/core/include/ans_manager_stub.h b/frameworks/ans/core/include/ans_manager_stub.h index 7947df74faa8ccb744a9e4d2f1ead237c7c55ea2..5366ed95044388ce7df63b8eb4d8d42b7047f116 100644 --- a/frameworks/ans/core/include/ans_manager_stub.h +++ b/frameworks/ans/core/include/ans_manager_stub.h @@ -106,6 +106,10 @@ public: virtual ErrCode ShellDump(const std::string &dumpOption, std::vector &dumpInfo) override; virtual ErrCode PublishContinuousTaskNotification(const sptr &request) override; virtual ErrCode CancelContinuousTaskNotification(const std::string &label, int32_t notificationId) override; + virtual ErrCode PublishReminder(sptr &reminder) override; + virtual ErrCode CancelReminder(const int32_t reminderId) override; + virtual ErrCode GetValidReminders(std::vector> &reminders) override; + virtual ErrCode CancelAllReminders() override; private: static const std::map> @@ -167,6 +171,10 @@ private: ErrCode HandleDoesSupportDoNotDisturbMode(MessageParcel &data, MessageParcel &reply); ErrCode HandlePublishContinuousTaskNotification(MessageParcel &data, MessageParcel &reply); ErrCode HandleCancelContinuousTaskNotification(MessageParcel &data, MessageParcel &reply); + ErrCode HandlePublishReminder(MessageParcel &data, MessageParcel &reply); + ErrCode HandleCancelReminder(MessageParcel &data, MessageParcel &reply); + ErrCode HandleGetValidReminders(MessageParcel &data, MessageParcel &reply); + ErrCode HandleCancelAllReminders(MessageParcel &data, MessageParcel &reply); template bool WriteParcelableVector(const std::vector> &parcelableVector, MessageParcel &reply, ErrCode &result); diff --git a/frameworks/ans/core/include/ans_notification.h b/frameworks/ans/core/include/ans_notification.h index e030626c541a698fb5c990cbe31a0da4c13e36f2..bb5480207904dc003314d39cee0162b1d58c83b3 100644 --- a/frameworks/ans/core/include/ans_notification.h +++ b/frameworks/ans/core/include/ans_notification.h @@ -639,6 +639,36 @@ public: */ ErrCode ShellDump(const std::string &dumpOption, std::vector &dumpInfo); + /** + * Publishes a scheduled reminder. + * + * @param reminder Indicates a reminder. + * @return Returns publish result. + */ + ErrCode PublishReminder(ReminderRequest &reminder); + + /** + * Cancels a specified reminder. + * + * @return Returns cancel result. + */ + ErrCode CancelReminder(const int32_t reminderId); + + /** + * Cancels all reminders of current third part application. + * + * @return Returns cancel result. + */ + ErrCode CancelAllReminders(); + + /** + * Obtains all valid reminder notifications set by the current application. + * + * @param[out] validReminders Indicates the vector to store the result. + * @return Returns get valid reminders result. + */ + ErrCode GetValidReminders(std::vector> &validReminders); + private: /** * Get Ans Manager proxy. diff --git a/frameworks/ans/core/src/ans_manager_proxy.cpp b/frameworks/ans/core/src/ans_manager_proxy.cpp index cdde8d21acbdb8cfd832d4ae3285e547841525db..9614eb9785174e4cdeb9d6d9504f49011a9969ec 100644 --- a/frameworks/ans/core/src/ans_manager_proxy.cpp +++ b/frameworks/ans/core/src/ans_manager_proxy.cpp @@ -20,6 +20,8 @@ #include "message_option.h" #include "message_parcel.h" #include "parcel.h" +#include "reminder_request_alarm.h" +#include "reminder_request_timer.h" namespace OHOS { namespace Notification { @@ -1941,6 +1943,148 @@ ErrCode AnsManagerProxy::CancelContinuousTaskNotification(const std::string &lab return result; } +ErrCode AnsManagerProxy::PublishReminder(sptr &reminder) +{ + ANSR_LOGI("PublishReminder"); + MessageParcel data; + if (!data.WriteInterfaceToken(AnsManagerProxy::GetDescriptor())) { + ANSR_LOGE("[PublishReminder] fail: write interface token failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + if (reminder == nullptr) { + ANSR_LOGW("[PublishReminder] fail: reminder is null ptr."); + return ERR_ANS_INVALID_PARAM; + } + if (!data.WriteUint8(static_cast(reminder->GetReminderType()))) { + ANSR_LOGE("[PublishReminder] fail: write reminder type failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + if (!data.WriteParcelable(reminder)) { + ANSR_LOGE("[Publish] fail: write reminder parcelable failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + + MessageParcel reply; + MessageOption option = {MessageOption::TF_SYNC}; + ErrCode result = InnerTransact(PUBLISH_REMINDER, option, data, reply); + if (result != ERR_OK) { + ANSR_LOGE("[PublishReminder] fail: transact ErrCode=%{public}d", result); + return ERR_ANS_TRANSACT_FAILED; + } + int32_t reminderId = -1; + if (!reply.ReadInt32(reminderId)) { + ANSR_LOGE("[PublishReminder] fail: derek read reminder id failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + reminder->SetReminderId(reminderId); + ANSR_LOGD("ReminderId=%{public}d", reminder->GetReminderId()); + return result; +} + +ErrCode AnsManagerProxy::CancelReminder(const int32_t reminderId) +{ + ANSR_LOGI("[CancelReminder]"); + MessageParcel data; + if (!data.WriteInterfaceToken(AnsManagerProxy::GetDescriptor())) { + ANSR_LOGE("[CancelReminder] fail: write interface token failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + if (!data.WriteInt32(reminderId)) { + ANSR_LOGE("[CancelReminder] fail: write reminder id failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + + MessageParcel reply; + MessageOption option = {MessageOption::TF_SYNC}; + ErrCode result = InnerTransact(CANCEL_REMINDER, option, data, reply); + if (result != ERR_OK) { + ANSR_LOGE("[CancelReminder] fail: transact ErrCode=%{public}d", result); + return ERR_ANS_TRANSACT_FAILED; + } + return result; +} + +ErrCode AnsManagerProxy::CancelAllReminders() +{ + ANSR_LOGI("[CancelAllReminders]"); + MessageParcel data; + if (!data.WriteInterfaceToken(AnsManagerProxy::GetDescriptor())) { + ANSR_LOGE("[CancelAllReminders] fail: write interface token failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + + MessageParcel reply; + MessageOption option = {MessageOption::TF_SYNC}; + ErrCode result = InnerTransact(CANCEL_ALL_REMINDERS, option, data, reply); + if (result != ERR_OK) { + ANSR_LOGE("[CancelAllReminders] fail: transact ErrCode=%{public}d", result); + return ERR_ANS_TRANSACT_FAILED; + } + return result; +} + +ErrCode AnsManagerProxy::GetValidReminders(std::vector> &reminders) +{ + ANSR_LOGI("[GetValidReminders]"); + MessageParcel data; + if (!data.WriteInterfaceToken(AnsManagerProxy::GetDescriptor())) { + ANSR_LOGE("[GetValidReminders] fail: write interface token failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + + MessageParcel reply; + MessageOption option = {MessageOption::TF_SYNC}; + ErrCode result = InnerTransact(GET_ALL_VALID_REMINDERS, option, data, reply); + if (result != ERR_OK) { + ANSR_LOGE("[GetValidReminders] fail: transact ErrCode=%{public}d", result); + return ERR_ANS_TRANSACT_FAILED; + } + uint8_t count = 0; + if (!reply.ReadUint8(count)) { + ANSR_LOGE("[GetValidReminders] fail: read reminder count failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + ANSR_LOGD("[GetValidReminders] count=%{public}u", count); + reminders.clear(); + result = ReadReminders(count, reply, reminders); + if (result != ERR_OK) { + ANSR_LOGE("[GetValidReminders] fail: ReadReminders ErrCode=%{public}d", result); + } else { + ANSR_LOGD("[GetValidReminders], size=%{public}zu", reminders.size()); + } + return result; +} + +ErrCode AnsManagerProxy::ReadReminders( + uint8_t &count, MessageParcel &reply, std::vector> &reminders) +{ + for (int i = 0; i < count; i++) { + uint8_t typeInfo = static_cast(ReminderRequest::ReminderType::INVALID); + if (!reply.ReadUint8(typeInfo)) { + ANSR_LOGE("Failed to read reminder type"); + return ERR_ANS_PARCELABLE_FAILED; + } + auto reminderType = static_cast(typeInfo); + sptr reminder; + if (ReminderRequest::ReminderType::ALARM == reminderType) { + ANSR_LOGD("[GetValidReminders] alarm"); + reminder = reply.ReadParcelable(); + } else if (ReminderRequest::ReminderType::TIMER == reminderType) { + ANSR_LOGD("[GetValidReminders] timer"); + reminder = reply.ReadParcelable(); + } else { + ANSR_LOGW("[GetValidReminders] type=%{public}d", typeInfo); + return ERR_ANS_INVALID_PARAM; + } + if (!reminder) { + ANSR_LOGE("[GetValidReminders] fail: Reminder ReadParcelable failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + reminders.push_back(reminder); + } + return ERR_OK; +} + ErrCode AnsManagerProxy::InnerTransact(uint32_t code, MessageOption &flags, MessageParcel &data, MessageParcel &reply) { auto remote = Remote(); diff --git a/frameworks/ans/core/src/ans_manager_stub.cpp b/frameworks/ans/core/src/ans_manager_stub.cpp index 9d3549f3b671880bcc32bc9f17eb72066e2ee984..b6352240e0088e30081a0a2f0365fc445880e86e 100644 --- a/frameworks/ans/core/src/ans_manager_stub.cpp +++ b/frameworks/ans/core/src/ans_manager_stub.cpp @@ -20,6 +20,8 @@ #include "message_option.h" #include "message_parcel.h" #include "parcel.h" +#include "reminder_request_alarm.h" +#include "reminder_request_timer.h" namespace OHOS { namespace Notification { @@ -195,6 +197,19 @@ const std::map(ReminderRequest::ReminderType::INVALID); + if (!data.ReadUint8(typeInfo)) { + ANSR_LOGE("Failed to read reminder type"); + return ERR_ANS_PARCELABLE_FAILED; + } + ReminderRequest::ReminderType reminderType = static_cast(typeInfo); + sptr reminder; + if (ReminderRequest::ReminderType::ALARM == reminderType) { + ANSR_LOGD("Publish alarm"); + reminder = data.ReadParcelable(); + } else if (ReminderRequest::ReminderType::TIMER == reminderType) { + ANSR_LOGD("Publish timer"); + reminder = data.ReadParcelable(); + } else { + ANSR_LOGE("Reminder type invalid"); + return ERR_ANS_INVALID_PARAM; + } + if (!reminder) { + ANSR_LOGE("Reminder ReadParcelable failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + + ErrCode result = PublishReminder(reminder); + + if (!reply.WriteInt32(reminder->GetReminderId())) { + ANSR_LOGE("Write back reminderId failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + return result; +} + +ErrCode AnsManagerStub::HandleCancelReminder(MessageParcel &data, MessageParcel &reply) +{ + ANSR_LOGI("HandleCancelReminder"); + int32_t reminderId = -1; + if (!data.ReadInt32(reminderId)) { + ANSR_LOGE("Read reminder id failed."); + return ERR_ANS_PARCELABLE_FAILED; + } + + ANSR_LOGD("ReminderId=%{public}d", reminderId); + return CancelReminder(reminderId); +} + +ErrCode AnsManagerStub::HandleCancelAllReminders(MessageParcel &data, MessageParcel &reply) +{ + return CancelAllReminders(); +} + +ErrCode AnsManagerStub::HandleGetValidReminders(MessageParcel &data, MessageParcel &reply) +{ + ANSR_LOGI("HandleGetValidReminders"); + std::vector> validReminders; + ErrCode result = GetValidReminders(validReminders); + + ANSR_LOGD("Write back size=%{public}zu", validReminders.size()); + if (!reply.WriteUint8(static_cast(validReminders.size()))) { + ANSR_LOGE("Write back reminder count failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + + for (auto it = validReminders.begin(); it != validReminders.end(); ++it) { + sptr reminder = (*it); + uint8_t reminderType = static_cast(reminder->GetReminderType()); + ANSR_LOGD("ReminderType=%{public}d", reminderType); + if (!reply.WriteUint8(reminderType)) { + ANSR_LOGW("Write reminder type failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + if (!reply.WriteParcelable(reminder)) { + ANSR_LOGW("Write reminder parcelable failed"); + return ERR_ANS_PARCELABLE_FAILED; + } + } + return result; +} + template bool AnsManagerStub::WriteParcelableVector( const std::vector> &parcelableVector, MessageParcel &reply, ErrCode &result) @@ -1638,5 +1733,28 @@ ErrCode AnsManagerStub::CancelContinuousTaskNotification(const std::string &labe ANS_LOGW("AnsManagerStub::CancelContinuousTaskNotification called!"); return ERR_INVALID_OPERATION; } +ErrCode AnsManagerStub::PublishReminder(sptr &reminder) +{ + ANS_LOGW("AnsManagerStub::PublishReminder called!"); + return ERR_INVALID_OPERATION; +} + +ErrCode AnsManagerStub::CancelReminder(const int32_t reminderId) +{ + ANS_LOGW("AnsManagerStub::CancelReminder called!"); + return ERR_INVALID_OPERATION; +} + +ErrCode AnsManagerStub::GetValidReminders(std::vector> &reminders) +{ + ANS_LOGW("AnsManagerStub::getValidReminders called!"); + return ERR_INVALID_OPERATION; +} + +ErrCode AnsManagerStub::CancelAllReminders() +{ + ANS_LOGW("AnsManagerStub::cancelAllReminders called!"); + return ERR_INVALID_OPERATION; +} } // namespace Notification } // namespace OHOS diff --git a/frameworks/ans/core/src/ans_notification.cpp b/frameworks/ans/core/src/ans_notification.cpp index f6d751e3e5bcdee9c080e7320e014edf36749e33..9f2214e90065f6b957171c559f25ed1ea4df8a43 100644 --- a/frameworks/ans/core/src/ans_notification.cpp +++ b/frameworks/ans/core/src/ans_notification.cpp @@ -18,6 +18,8 @@ #include "ans_inner_errors.h" #include "ans_log_wrapper.h" #include "iservice_registry.h" +#include "reminder_request_alarm.h" +#include "reminder_request_timer.h" #include "system_ability_definition.h" namespace OHOS { @@ -862,6 +864,58 @@ ErrCode AnsNotification::ShellDump(const std::string &dumpOption, std::vectorShellDump(dumpOption, dumpInfo); } +ErrCode AnsNotification::PublishReminder(ReminderRequest &reminder) +{ + if (!GetAnsManagerProxy()) { + 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; + } + ErrCode code = ansManagerProxy_->PublishReminder(tarReminder); + reminder.SetReminderId(tarReminder->GetReminderId()); + return code; +} + +ErrCode AnsNotification::CancelReminder(const int32_t reminderId) +{ + if (!GetAnsManagerProxy()) { + ANS_LOGE("GetAnsManagerProxy fail."); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + return ansManagerProxy_->CancelReminder(reminderId); +} + +ErrCode AnsNotification::CancelAllReminders() +{ + if (!GetAnsManagerProxy()) { + ANS_LOGE("GetAnsManagerProxy fail."); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + return ansManagerProxy_->CancelAllReminders(); +} + +ErrCode AnsNotification::GetValidReminders(std::vector> &validReminders) +{ + if (!GetAnsManagerProxy()) { + ANS_LOGE("GetAnsManagerProxy fail."); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + return ansManagerProxy_->GetValidReminders(validReminders); +} + bool AnsNotification::GetAnsManagerProxy() { if (!ansManagerProxy_) { diff --git a/frameworks/ans/native/src/reminder_helper.cpp b/frameworks/ans/native/src/reminder_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa36349053cc7d932c44893d24380beafd0aa3e8 --- /dev/null +++ b/frameworks/ans/native/src/reminder_helper.cpp @@ -0,0 +1,85 @@ +/* + * 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 "ans_notification.h" +#include "application_env_impl.h" +#include "iservice_registry.h" +#include "notification_helper.h" +#include "singleton.h" +#include "system_ability_definition.h" + +#include "reminder_helper.h" + +namespace OHOS { +namespace Notification { +ErrCode ReminderHelper::PublishReminder(ReminderRequest &reminder) +{ + ANSR_LOGI("PublishReminder start"); + NotificationSlot slot(reminder.GetSlotType()); + NotificationHelper::AddNotificationSlot(slot); + return DelayedSingleton::GetInstance()->PublishReminder(reminder); +} + +ErrCode ReminderHelper::CancelReminder(const int32_t reminderId) +{ + ANSR_LOGI("CancelReminder start"); + return DelayedSingleton::GetInstance()->CancelReminder(reminderId); +} + +ErrCode ReminderHelper::CancelAllReminders() +{ + ANSR_LOGI("CancelAllReminders start"); + return DelayedSingleton::GetInstance()->CancelAllReminders(); +} + +bool ReminderHelper::CheckPermission() +{ + ANSR_LOGI("CheckPermission"); + AppExecFwk::ApplicationEnvImpl* application = AppExecFwk::ApplicationEnvImpl::GetInstance(); + std::string pkgName = application->GetBundleName(); + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + ANSR_LOGE("Permission denied"); + return false; + } + auto bundleManager = + iface_cast(systemManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID)); + if (bundleManager->CheckPermission(pkgName, "ohos.permission.PUBLISH_AGENT_REMINDER") != 0) { + ANSR_LOGE("Permission denied"); + return false; + } + return true; +} + +ErrCode ReminderHelper::GetValidReminders(std::vector> &validReminders) +{ + ANSR_LOGI("GetValidReminders start"); + return DelayedSingleton::GetInstance()->GetValidReminders(validReminders); +} + +ErrCode AddNotificationSlot(const NotificationSlot &slot) +{ + ANSR_LOGI("AddNotificationSlot start"); + return DelayedSingleton::GetInstance()->AddNotificationSlot(slot); +} + +ErrCode RemoveNotificationSlot(const NotificationConstant::SlotType &slotType) +{ + ANSR_LOGI("RemoveNotificationSlot start"); + return DelayedSingleton::GetInstance()->RemoveNotificationSlot(slotType); +} +} +} \ No newline at end of file diff --git a/frameworks/ans/native/src/reminder_request.cpp b/frameworks/ans/native/src/reminder_request.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f7f16d4e5274500e12e4b0d387e1430d21bb42e --- /dev/null +++ b/frameworks/ans/native/src/reminder_request.cpp @@ -0,0 +1,645 @@ +/* + * 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 "want_agent_helper.h" + +#include "reminder_request.h" + +namespace OHOS { +namespace Notification { +int32_t ReminderRequest::GLOBAL_ID = 0; +const uint64_t ReminderRequest::INVALID_LONG_VALUE = 0; +const uint16_t ReminderRequest::MILLI_SECONDS = 1000; +const uint16_t ReminderRequest::SAME_TIME_DISTINGUISH_MILLISECONDS = 1000; +const uint8_t ReminderRequest::REMINDER_STATUS_INACTIVE = 0; +const uint8_t ReminderRequest::REMINDER_STATUS_SHOWING = 4; +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_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"; + +ReminderRequest::ReminderRequest() +{ + wantAgentInfo_ = wantAgentInfo_ == nullptr ? std::make_shared() : wantAgentInfo_; +} + +ReminderRequest::ReminderRequest(const ReminderRequest &other) +{ + this->actionButtonMap_ = other.actionButtonMap_; + this->content_ = other.content_; + this->expiredContent_ = other.expiredContent_; + this->notificationId_ = other.notificationId_; + this->reminderId_ = other.reminderId_; + this->reminderType_ = other.reminderType_; + this->slotType_ = other.slotType_; + this->title_ = other.title_; + this->triggerTimeInMilli_ = other.triggerTimeInMilli_; + this->wantAgentInfo_ = other.wantAgentInfo_; +} + +ReminderRequest::ReminderRequest(ReminderType reminderType) +{ + reminderType_ = reminderType; + wantAgentInfo_ = wantAgentInfo_ == nullptr ? std::make_shared() : wantAgentInfo_; +} + +bool ReminderRequest::CanRemove() +{ + if ((state_ & REMINDER_STATUS_SHOWING) == 0) { + return true; + } + return false; +} + +std::string ReminderRequest::Dump() const +{ + struct tm *timeInfo; + const time_t nextTriggerTime = static_cast(triggerTimeInMilli_ / 1000); + timeInfo = localtime(&nextTriggerTime); + uint8_t dateTimeLen = 80; + char dateTimeBuffer[dateTimeLen]; + (void)strftime(dateTimeBuffer, dateTimeLen, "%Y-%m-%d %H:%M:%S", timeInfo); + return "Reminder[" + "id=" + std::to_string(reminderId_) + + ", type=" + std::to_string(static_cast(reminderType_)) + + ", state=" + GetState(state_) + + ", nextTriggerTime=" + dateTimeBuffer + + "]"; +} + +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)); + return *this; + } + ActionButtonInfo actionButtonInfo; + actionButtonInfo.type = type; + actionButtonInfo.title = title; + 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::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_); +} + +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, "onClose()"); + if (updateNext) { + uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(false); + if (nextTriggerTime == INVALID_LONG_VALUE) { + isExpired_ = true; + } else { + SetTriggerTimeInMilli(nextTriggerTime); + } + } +} + +bool ReminderRequest::OnDateTimeChange() +{ + uint64_t nextTriggerTime = PreGetNextTriggerTimeIgnoreSnooze(false); + return HandleSysTimeChange(triggerTimeInMilli_, nextTriggerTime); +} + +bool ReminderRequest::HandleSysTimeChange(uint64_t oriTriggerTime, uint64_t optTriggerTime) +{ + if (isExpired_) { + return false; + } + bool showImmediately = false; + if (optTriggerTime != INVALID_LONG_VALUE && optTriggerTime <= oriTriggerTime) { + // case1. switch to a previous time + SetTriggerTimeInMilli(optTriggerTime); + } else { + time_t now; + time(&now); // unit is seconds. + if (static_cast(now) < 0) { + ANSR_LOGE("Get now time error"); + return false; + } + if (oriTriggerTime <= (static_cast(now) * MILLI_SECONDS)) { + // 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. + 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, oldZoneTriggerTime:%{public}llu, newZoneTriggerTime:%{public}llu", + (unsigned long long)oldZoneTriggerTime, (unsigned long long)newZoneTriggerTime); + bool showImmediately = false; + if (optTriggerTime != INVALID_LONG_VALUE && oldZoneTriggerTime < newZoneTriggerTime) { + // case1. timezone change to smaller + SetTriggerTimeInMilli(optTriggerTime); + } else { + time_t now; + time(&now); // unit is seconds. + if (static_cast(now) < 0) { + ANSR_LOGE("Get now time error"); + return false; + } + if (newZoneTriggerTime <= (static_cast(now))) { + // case2. timezone change to larger + showImmediately = true; + } else { + SetTriggerTimeInMilli(newZoneTriggerTime); + showImmediately = false; + } + } + return showImmediately; +} + +void ReminderRequest::OnSameNotificationIdCovered() +{ + SetState(false, REMINDER_STATUS_SHOWING, "OnSameNotificationIdCovered"); +} + +void ReminderRequest::OnShow(bool isSysTimeChanged, bool allowToNotify) +{ + if (allowToNotify) { + SetState(true, REMINDER_STATUS_SHOWING, "OnShow"); + } + UpdateNextReminder(); +} + +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); + return HandleTimeZoneChange(oldZoneTriggerTime, newZoneTriggerTime, nextTriggerTime); +} + +ReminderRequest& ReminderRequest::SetNotificationId(int32_t notificationId) +{ + notificationId_ = notificationId; + return *this; +} + +ReminderRequest& ReminderRequest::SetSlotType(const NotificationConstant::SlotType &slotType) +{ + slotType_ = slotType; + 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; +} + +std::map ReminderRequest::GetActionButtons() + const +{ + return actionButtonMap_; +} + +std::string ReminderRequest::GetContent() const +{ + return content_; +} + +std::string ReminderRequest::GetExpiredContent() const +{ + return expiredContent_; +} + +int32_t ReminderRequest::GetNotificationId() const +{ + return notificationId_; +} + +sptr ReminderRequest::GetNotificationRequest() const +{ + return notificationRequest_; +} + +int32_t ReminderRequest::GetReminderId() const +{ + return reminderId_; +} + +void ReminderRequest::SetReminderId(int32_t reminderId) +{ + reminderId_ = reminderId; +} + +NotificationConstant::SlotType ReminderRequest::GetSlotType() const +{ + return slotType_; +} + +uint8_t ReminderRequest::GetState() const +{ + return state_; +} + +std::string ReminderRequest::GetTitle() const +{ + return title_; +} + +uint64_t ReminderRequest::GetTriggerTimeInMilli() const +{ + return triggerTimeInMilli_; +} + +std::shared_ptr ReminderRequest::GetWantAgentInfo() const +{ + return wantAgentInfo_; +} + +ReminderRequest::ReminderType ReminderRequest::GetReminderType() const +{ + return reminderType_; +} + +bool ReminderRequest::UpdateNextReminder() +{ + return false; +} + +void ReminderRequest::UpdateNotificationRequest(UpdateNotificationType type, std::string extra) +{ + ANSR_LOGI("UpdateNotification type=%{public}d", static_cast(type)); + switch (type) { + case UpdateNotificationType::COMMON: { + UpdateNotificationCommon(); + break; + } + case UpdateNotificationType::ACTION_BUTTON: { + AddActionButtons(); + break; + } + case UpdateNotificationType::REMOVAL_WANT_AGENT: { + AddRemovalWantAgent(); + break; + } + case UpdateNotificationType::CONTENT: { + break; + } + default: + break; + } +} + +bool ReminderRequest::Marshalling(Parcel &parcel) const +{ + // write string + if (!parcel.WriteString(content_)) { + ANSR_LOGE("Failed to write content"); + return false; + } + if (!parcel.WriteString(expiredContent_)) { + ANSR_LOGE("Failed to write expiredContent"); + return false; + } + if (!parcel.WriteString(title_)) { + ANSR_LOGE("Failed to write title"); + return false; + } + if (!parcel.WriteString(wantAgentInfo_->abilityName)) { + ANSR_LOGE("Failed to write wantAgentInfo`s abilityName"); + return false; + } + if (!parcel.WriteString(wantAgentInfo_->pkgName)) { + ANSR_LOGE("Failed to write wantAgentInfo`s pkgName"); + return false; + } + + // write int + if (!parcel.WriteInt32(reminderId_)) { + ANSR_LOGE("Failed to write reminderId"); + return false; + } + if (!parcel.WriteInt32(notificationId_)) { + ANSR_LOGE("Failed to write notificationId"); + return false; + } + if (!parcel.WriteUint64(triggerTimeInMilli_)) { + ANSR_LOGE("Failed to write triggerTimeInMilli"); + return false; + } + + // write enum + if (!parcel.WriteUint8(static_cast(reminderType_))) { + ANSR_LOGE("Failed to write reminder type"); + return false; + } + if (!parcel.WriteInt32(static_cast(slotType_))) { + ANSR_LOGE("Failed to write slot type"); + return false; + } + + // write map + int32_t buttonMapSize = static_cast(actionButtonMap_.size()); + if (!parcel.WriteInt32(buttonMapSize)) { + ANSR_LOGE("Failed to write action button size"); + return false; + } + for (auto it = actionButtonMap_.begin(); it != actionButtonMap_.end(); ++it) { + if (!parcel.WriteUint8(static_cast(it->first))) { + ANSR_LOGE("Failed to write action button type"); + return false; + } + if (!parcel.WriteString(static_cast(it->second.title))) { + ANSR_LOGE("Failed to write action button title"); + return false; + } + } + return true; +} + +ReminderRequest *ReminderRequest::Unmarshalling(Parcel &parcel) +{ + auto objptr = new ReminderRequest(); + if ((objptr != nullptr) && !objptr->ReadFromParcel(parcel)) { + delete objptr; + objptr = nullptr; + } + + return objptr; +} + +bool ReminderRequest::ReadFromParcel(Parcel &parcel) +{ + // read string + if (!parcel.ReadString(content_)) { + ANSR_LOGE("Failed to read content"); + return false; + } + if (!parcel.ReadString(expiredContent_)) { + ANSR_LOGE("to read expiredContent"); + return false; + } + if (!parcel.ReadString(title_)) { + ANSR_LOGE("Failed to read title"); + return false; + } + if (!parcel.ReadString(wantAgentInfo_->abilityName)) { + ANSR_LOGE("Failed to read wantAgentInfo`s abilityName"); + return false; + } + if (!parcel.ReadString(wantAgentInfo_->pkgName)) { + ANSR_LOGE("Failed to read wantAgentInfo`s pkgName"); + return false; + } + + // read int + int32_t tempReminderId = -1; + if (!parcel.ReadInt32(tempReminderId)) { + ANSR_LOGE("Failed to read tempReminderId"); + return false; + } + reminderId_ = tempReminderId == -1 ? reminderId_ : tempReminderId; + + if (!parcel.ReadInt32(notificationId_)) { + ANSR_LOGE("Failed to read notificationId"); + return false; + } + if (!parcel.ReadUint64(triggerTimeInMilli_)) { + ANSR_LOGE("Failed to read triggerTimeInMilli"); + return false; + } + + // read enum + uint8_t reminderType = static_cast(ReminderType::INVALID); + if (!parcel.ReadUint8(reminderType)) { + ANSR_LOGE("Failed to read reminderType"); + return false; + } + reminderType_ = static_cast(reminderType); + + int32_t slotType = static_cast(NotificationConstant::SlotType::OTHER); + if (!parcel.ReadInt32(slotType)) { + ANSR_LOGE("Failed to read slotType"); + return false; + } + slotType_ = static_cast(slotType); + + // read map + int32_t buttonMapSize = 0; + if (!parcel.ReadInt32(buttonMapSize)) { + ANSR_LOGE("Failed to read buttonMapSize"); + return false; + } + for (int i = 0; i < buttonMapSize; i++) { + uint8_t buttonType = static_cast(ActionButtonType::INVALID); + if (!parcel.ReadUint8(buttonType)) { + ANSR_LOGE("Failed to read buttonType"); + return false; + } + ActionButtonType type = static_cast(buttonType); + std::string title = parcel.ReadString(); + ActionButtonInfo info; + info.type = type; + info.title = title; + actionButtonMap_.insert(std::pair(type, info)); + } + InitNotificationRequest(); + return true; +} + +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 +} + +std::string ReminderRequest::GetState(const uint8_t state) const +{ + std::string stateInfo = "Inactive"; + if (state == REMINDER_STATUS_INACTIVE) { + return stateInfo; + } else { + if ((state & REMINDER_STATUS_SHOWING) != 0) { + stateInfo = "Showing"; + } + } + return stateInfo; +} + +void ReminderRequest::AddActionButtons() +{ + int requestCode = 10; + std::vector flags; + flags.push_back(WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG); + for (auto it = actionButtonMap_.begin(); it != actionButtonMap_.end(); ++it) { + auto want = std::make_shared(); + auto type = it->first; + if (type == ActionButtonType::CLOSE) { + want->SetAction(REMINDER_EVENT_CLOSE_ALERT); + ANSR_LOGD("Add action button, type is close"); + } + want->SetParam("REMINDER_ID", reminderId_); + std::vector> wants; + wants.push_back(want); + auto title = static_cast(it->second.title); + WantAgent::WantAgentInfo buttonWantAgentInfo( + requestCode, + WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT, + flags, + wants, + nullptr + ); + std::shared_ptr buttonWantAgent = + WantAgent::WantAgentHelper::GetWantAgent(buttonWantAgentInfo); + std::shared_ptr actionButton + = NotificationActionButton::Create(nullptr, title, buttonWantAgent); + notificationRequest_->AddActionButton(actionButton); + } +} + +void ReminderRequest::AddRemovalWantAgent() +{ + int requestCode = 10; + std::vector flags; + flags.push_back(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); + WantAgent::WantAgentInfo wantAgentInfo( + requestCode, + WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT, + flags, + wants, + nullptr + ); + std::shared_ptr wantAgent = WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo); + notificationRequest_->SetRemovalWantAgent(wantAgent); +} + +void ReminderRequest::SetWantAgent() +{ + 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); + WantAgent::WantAgentInfo wantAgentInfo( + requestCode, + WantAgent::WantAgentConstant::OperationType::START_ABILITY, + flags, + wants, + nullptr + ); + std::shared_ptr wantAgent = WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo); + 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_ &= ~newState; + } + ANSR_LOGI("Switch the reminder(id=%{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::UpdateNotificationCommon() +{ + time_t now; + (void)time(&now); // unit is seconds. + notificationRequest_->SetDeliveryTime(static_cast(now * MILLI_SECONDS)); +} +} +} \ 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 new file mode 100644 index 0000000000000000000000000000000000000000..7cbc22645a58ed9763a0e5b0f5351e25c135938f --- /dev/null +++ b/frameworks/ans/native/src/reminder_request_alarm.cpp @@ -0,0 +1,266 @@ +/* + * 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 "reminder_request_alarm.h" +#include "ans_log_wrapper.h" + +namespace OHOS { +namespace Notification { +const uint8_t ReminderRequestAlarm::DAYS_PER_WEEK = 7; +const uint8_t ReminderRequestAlarm::MONDAY = 1; +const uint8_t ReminderRequestAlarm::SUNDAY = 7; +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; + +ReminderRequestAlarm::ReminderRequestAlarm(uint8_t hour, uint8_t minute, const std::vector daysOfWeek) + : ReminderRequest(ReminderRequest::ReminderType::ALARM) +{ + hour_ = hour; + minute_ = minute; + CheckParamValid(); + SetDaysOfWeek(true, daysOfWeek); + SetTriggerTimeInMilli(GetNextTriggerTime(true)); +} + +ReminderRequestAlarm::ReminderRequestAlarm(const ReminderRequestAlarm &other) : ReminderRequest(other) +{ + this->hour_ = other.hour_; + this->minute_ = other.minute_; + this->repeatDays_ = other.repeatDays_; + ANSR_LOGD("hour_=%{public}d, minute_=%{public}d, repeatDays_=%{public}d", hour_, minute_, repeatDays_); +} + +void ReminderRequestAlarm::CheckParamValid() const +{ + if (hour_ >= HOURS_PER_DAY || hour_ < 0) { + ANSR_LOGE("setted hour is not between [0, 24)"); + throw std::invalid_argument("setted hour is not between [0, 24)"); + } + if (minute_ < 0 || minute_ >= MINUTES_PER_HOUR) { + ANSR_LOGE("setted minute is not between [0, 60)"); + throw std::invalid_argument("setted minute is not between [0, 60)"); + } +} + +void ReminderRequestAlarm::SetDaysOfWeek(bool set, 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"); + throw std::invalid_argument("The length of daysOfWeek should not larger than 7"); + } + for (std::vector::iterator it = daysOfWeek.begin(); it != daysOfWeek.end(); ++it) { + if (*it < MONDAY || *it > SUNDAY) { + continue; + } + if (set) { + repeatDays_ |= 1 << (*it - 1); + } else { + repeatDays_ &= ~(1 << (*it - 1)); + } + } +} + +uint64_t ReminderRequestAlarm::PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const +{ + return GetNextTriggerTime(false); +} + +uint64_t ReminderRequestAlarm::GetNextTriggerTime(bool forceToGetNext) const +{ + time_t now; + (void)time(&now); // unit is seconds. + struct tm *nowTime = localtime(&now); + + struct tm tar; + tar.tm_year = nowTime->tm_year; + tar.tm_mon = nowTime->tm_mon; + tar.tm_mday = nowTime->tm_mday; + 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); + + const time_t target = mktime(&tar); + int8_t nextDayInterval = GetNextAlarm(now, target); + time_t nextTriggerTime = 0; + if (nextDayInterval == INVALID_INT_VALUE) { + if (now >= target) { + if (forceToGetNext) { + nextTriggerTime = target + 1 * HOURS_PER_DAY * SECONDS_PER_HOUR; + } + } else { + nextTriggerTime = target; + } + } else { + nextTriggerTime = target + nextDayInterval * HOURS_PER_DAY * SECONDS_PER_HOUR; + } + 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); + + if (static_cast(nextTriggerTime) <= 0) { + return 0; + } + return static_cast(nextTriggerTime) * ReminderRequest::MILLI_SECONDS; +} + +int8_t ReminderRequestAlarm::GetNextAlarm(const time_t now, const time_t target) const +{ + if (repeatDays_ == 0) { + return INVALID_INT_VALUE; + } + int today = gmtime(&now)->tm_wday; + int dayCount = now >= target ? 1 : 0; + for (; dayCount <= DAYS_PER_WEEK; dayCount++) { + int day = (today + dayCount) % DAYS_PER_WEEK; + day = (day == 0) ? SUNDAY : day; + if (IsRepeatDay(day)) { + break; + } + } + ANSR_LOGI("NextDayInterval is %{public}d", dayCount); + return dayCount; +} + +bool ReminderRequestAlarm::IsRepeatDay(int day) const +{ + return (repeatDays_ & (1 << (day - 1))) > 0; +} + +std::vector ReminderRequestAlarm::GetDaysOfWeek() const +{ + std::vector repeatDays; + int days[] = {1, 2, 3, 4, 5, 6, 7}; + int len = sizeof(days) / sizeof(int); + for (int i = 0; i < len; i++) { + if (IsRepeatDay(days[i])) { + repeatDays.push_back(days[i]); + } + } + return repeatDays; +} + +uint8_t ReminderRequestAlarm::GetHour() const +{ + return hour_; +} + +uint8_t ReminderRequestAlarm::GetMinute() const +{ + return minute_; +} + +uint8_t ReminderRequestAlarm::GetRepeatDay() const +{ + return repeatDays_; +} + +bool ReminderRequestAlarm::OnDateTimeChange() +{ + return ReminderRequest::OnDateTimeChange(); +} + +bool ReminderRequestAlarm::OnTimeZoneChange() +{ + return ReminderRequest::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); + return true; + } else { + ANSR_LOGD("Set reminder to expired"); + SetExpired(true); + return false; + } +} + +bool ReminderRequestAlarm::Marshalling(Parcel &parcel) const +{ + ReminderRequest::Marshalling(parcel); + + // write int + 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(repeatDays_)) { + 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)) { + delete objptr; + objptr = nullptr; + } + return objptr; +} + +bool ReminderRequestAlarm::ReadFromParcel(Parcel &parcel) +{ + ReminderRequest::ReadFromParcel(parcel); + + // read int + 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(repeatDays_)) { + ANSR_LOGE("Failed to read repeatDays"); + return false; + } + ANSR_LOGD("hour_=%{public}d, minute_=%{public}d, repeatDays_=%{public}d", hour_, minute_, repeatDays_); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..00b975cc7220f3f3dac2370d35cb9f5a37ef7d2c --- /dev/null +++ b/frameworks/ans/native/src/reminder_request_timer.cpp @@ -0,0 +1,140 @@ +/* + * 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 +#include + +#include "ans_log_wrapper.h" +#include "time_service_client.h" + +#include "reminder_request_timer.h" + +namespace OHOS { +namespace Notification { +ReminderRequestTimer::ReminderRequestTimer(uint64_t countDownTimeInSeconds) + : ReminderRequest(ReminderRequest::ReminderType::TIMER) +{ + CheckParamsValid(countDownTimeInSeconds); + countDownTimeInSeconds_ = countDownTimeInSeconds; + time_t now; // unit is seconds. + (void)time(&now); + ReminderRequest::SetTriggerTimeInMilli( + (static_cast(now) + countDownTimeInSeconds_) * ReminderRequest::MILLI_SECONDS); + sptr timer = MiscServices::TimeServiceClient::GetInstance(); + firstRealTimeInMilliSeconds_ = timer->GetBootTimeMs(); +} + +ReminderRequestTimer::ReminderRequestTimer(const ReminderRequestTimer &other) : ReminderRequest(other) +{ + firstRealTimeInMilliSeconds_ = other.firstRealTimeInMilliSeconds_; + countDownTimeInSeconds_ = other.countDownTimeInSeconds_; +} + +uint64_t ReminderRequestTimer::GetInitInfo() const +{ + return countDownTimeInSeconds_; +} + +uint64_t ReminderRequestTimer::PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const +{ + ANSR_LOGD("countdonw time not support PreGetNextTriggerTimeIgnoreSnooze"); + return ReminderRequest::INVALID_LONG_VALUE; +} + +bool ReminderRequestTimer::OnDateTimeChange() +{ + UpdateTimeInfo("onDateTimeChange"); + return false; +} + +bool ReminderRequestTimer::OnTimeZoneChange() +{ + UpdateTimeInfo("onTimeZoneChange"); + return false; +} + +bool ReminderRequestTimer::UpdateNextReminder() +{ + ANSR_LOGD("countdonw time not support repeat reminder, no need to update next triggerTime"); + SetExpired(true); + return false; +} + +void ReminderRequestTimer::CheckParamsValid(const uint64_t countDownTimeInSeconds) const +{ + if (countDownTimeInSeconds == 0 || countDownTimeInSeconds >= (UINT64_MAX / ReminderRequest::MILLI_SECONDS)) { + ANSR_LOGE("Illegal count down time, please check the description of the constructor"); + throw std::invalid_argument("Illegal count down time, please check the description of the constructor"); + } +} + +void ReminderRequestTimer::UpdateTimeInfo(const std::string description) +{ + if (IsExpired()) { + return; + } + ANSR_LOGD("%{public}s, update countdown time trigger time", description.c_str()); + time_t now; + (void)time(&now); // unit is seconds. + whenToChangeSysTime_ = static_cast(now) * MILLI_SECONDS; + sptr timer = MiscServices::TimeServiceClient::GetInstance(); + int64_t bootTime = timer->GetBootTimeMs(); + SetTriggerTimeInMilli(whenToChangeSysTime_ + (countDownTimeInSeconds_ * MILLI_SECONDS - + (bootTime - firstRealTimeInMilliSeconds_))); +} + +bool ReminderRequestTimer::Marshalling(Parcel &parcel) const +{ + ReminderRequest::Marshalling(parcel); + + // write int + if (!parcel.WriteUint64(firstRealTimeInMilliSeconds_)) { + ANSR_LOGE("Failed to write firstRealTimeInMilliSeconds"); + return false; + } + if (!parcel.WriteUint64(countDownTimeInSeconds_)) { + ANSR_LOGE("Failed to write countDownTimeInSeconds"); + return false; + } + return true; +} + +ReminderRequestTimer *ReminderRequestTimer::Unmarshalling(Parcel &parcel) +{ + auto objptr = new ReminderRequestTimer(); + if ((objptr != nullptr) && !objptr->ReadFromParcel(parcel)) { + delete objptr; + objptr = nullptr; + } + return objptr; +} + +bool ReminderRequestTimer::ReadFromParcel(Parcel &parcel) +{ + ReminderRequest::ReadFromParcel(parcel); + + // read int + if (!parcel.ReadUint64(firstRealTimeInMilliSeconds_)) { + ANSR_LOGE("Failed to read firstRealTimeInMilliSeconds"); + return false; + } + if (!parcel.ReadUint64(countDownTimeInSeconds_)) { + ANSR_LOGE("Failed to read countDownTimeInSeconds"); + return false; + } + return true; +} +} +} \ No newline at end of file diff --git a/frameworks/ans/native/test/unittest/BUILD.gn b/frameworks/ans/native/test/unittest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..734390a46a608466d285d40ee1027c12b4f10b90 --- /dev/null +++ b/frameworks/ans/native/test/unittest/BUILD.gn @@ -0,0 +1,81 @@ +# 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. + +import("//base/notification/ans_standard/notification.gni") +import("//build/ohos.gni") +import("//build/test.gni") + +module_output_path = "ans_reminder/unittest" + +ohos_unittest("ans_reminder_unit_test") { + module_out_path = module_output_path + + include_dirs = [ + ".", + "include", + "//foundation/appexecfwk/standard/libs/libeventhandler/src", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//utils/native/base/include", + "//utils/system/safwk/native/include", + "/${services_path}/ans/include", + "${services_path}/ans/test/unittest/mock/include", + "//foundation/distributeddatamgr/distributeddatamgr/services/distributeddataservice/adapter/include/autils", + "//foundation/distributeddatamgr/distributeddatamgr/frameworks/innerkitsimpl/distributeddatafwk/include", + "//foundation/distributeddatamgr/distributeddatamgr/services/distributeddataservice/adapter/include/log", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata/include", + "//foundation/distributeddatamgr/distributeddatamgr/frameworks/innerkitsimpl/distributeddatafwk/src", + "//foundation/distributeddatamgr/distributeddatamgr/services/distributeddataservice/adapter/include/dfx", + "//developtools/bytrace_standard/interfaces/innerkits/native/include", + ] + + sources = [ + "${native_path}/test/unittest/reminder_request_alarm_test.cpp", + "${native_path}/test/unittest/reminder_request_test.cpp", + "${native_path}/test/unittest/reminder_request_timer_test.cpp", + ] + + configs = [ "//utils/native/base:utils_config" ] + + deps = [ + "${core_path}:ans_core", + "${frameworks_path}/ans/native:ans_innerkits", + "${frameworks_path}/wantagent:wantagent_innerkits", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:appexecfwk_core", + "appexecfwk_standard:libeventhandler", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr_standard:samgr_proxy", + ] + + subsystem_name = "notification" + part_name = "ans_standard" +} + +group("unittest") { + testonly = true + deps = [] + + deps += [ ":ans_reminder_unit_test" ] +} diff --git a/frameworks/ans/native/test/unittest/reminder_request_alarm_test.cpp b/frameworks/ans/native/test/unittest/reminder_request_alarm_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e76090e706690195f1f7761f6000140930a34e9 --- /dev/null +++ b/frameworks/ans/native/test/unittest/reminder_request_alarm_test.cpp @@ -0,0 +1,210 @@ +/* + * 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 + +#include "ans_log_wrapper.h" +#include "reminder_request_alarm.h" +#include "reminder_helper.h" + +using namespace testing::ext; +namespace OHOS { +namespace Notification { +class ReminderRequestAlarmTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() + { + ReminderHelper::CancelAllReminders(); + } +}; + +/** + * @tc.number : initHour_00100 + * @tc.name : + * @tc.desc : set hour < 0 should throw exception. + */ +HWTEST_F(ReminderRequestAlarmTest, initHour_00100, Function | SmallTest | Level1) +{ + std::vector daysOfWeek; + try { + auto rrc = std::make_shared(-1, 1, daysOfWeek); + EXPECT_TRUE(false) << "hour < 0 should throw exception."; + } catch (const std::invalid_argument &e) { + ANSR_LOGI("hour < 0 throw exception."); + } +} + +/** + * @tc.number : initHour_00200 + * @tc.name : + * @tc.desc : set hour > 23 should throw exception. + */ +HWTEST_F(ReminderRequestAlarmTest, initHour_00200, Function | SmallTest | Level1) +{ + std::vector daysOfWeek; + try { + auto rrc = std::make_shared(24, 1, daysOfWeek); + EXPECT_TRUE(false) << "hour > 23 should throw exception."; + } catch (const std::invalid_argument &e) { + ANSR_LOGI("hour > 23 throw exception."); + } +} + +/** + * @tc.number : initHour_00300 + * @tc.name : + * @tc.desc : test set edge value of hour (0 and 23). + */ +HWTEST_F(ReminderRequestAlarmTest, initHour_00300, Function | SmallTest | Level1) +{ + std::vector daysOfWeek; + auto rrc = std::make_shared(0, 1, daysOfWeek); + EXPECT_TRUE(rrc->GetHour() == 0) << "hour should be 0"; + + auto rrcB = std::make_shared(23, 1, daysOfWeek); + EXPECT_TRUE(rrcB->GetHour() == 23) << "hour should be 23"; + + auto rrcC = std::make_shared(1, 1, daysOfWeek); + EXPECT_TRUE(rrcC->GetHour() == 1) << "hour should be 1"; + + auto rrcD = std::make_shared(22, 1, daysOfWeek); + EXPECT_TRUE(rrcD->GetHour() == 22) << "hour should be 22"; + + auto rrcE = std::make_shared(12, 1, daysOfWeek); + EXPECT_TRUE(rrcE->GetHour() == 12) << "hour should be 12"; +} + +/** + * @tc.number : initHour_00400 + * @tc.name : + * @tc.desc : set minute < 0 should throw exception. + */ +HWTEST_F(ReminderRequestAlarmTest, initHour_00400, Function | SmallTest | Level1) +{ + std::vector daysOfWeek; + try { + auto rrc = std::make_shared(1, -1, daysOfWeek); + EXPECT_TRUE(false) << "minute < 0 should throw exception."; + } catch (const std::invalid_argument &e) { + ANSR_LOGI("minute < 0 throw exception."); + } +} + +/** + * @tc.number : initHour_00500 + * @tc.name : + * @tc.desc : set minute > 59 should throw exception. + */ +HWTEST_F(ReminderRequestAlarmTest, initHour_00500, Function | SmallTest | Level1) +{ + std::vector daysOfWeek; + try { + auto rrc = std::make_shared(1, 60, daysOfWeek); + EXPECT_TRUE(false) << "minute > 59 should throw exception."; + } catch (const std::invalid_argument &e) { + ANSR_LOGI("minute > 59 throw exception."); + } +} + +/** + * @tc.number : initHour_00600 + * @tc.name : + * @tc.desc : test set edge value of minute (0 and 59). + */ +HWTEST_F(ReminderRequestAlarmTest, initHour_00600, Function | SmallTest | Level1) +{ + std::vector daysOfWeek; + auto rrc = std::make_shared(0, 0, daysOfWeek); + EXPECT_TRUE(rrc->GetMinute() == 0) << "minute should be 0"; + + auto rrcB = std::make_shared(23, 59, daysOfWeek); + EXPECT_TRUE(rrcB->GetMinute() == 59) << "minute should be 59"; +} + +/** + * @tc.number : initDaysOfWeek_00100 + * @tc.name : + * @tc.desc : test set daysOfWeek with normal value. + */ +HWTEST_F(ReminderRequestAlarmTest, initDaysOfWeek_00100, Function | SmallTest | Level1) +{ + uint8_t arr[] = {1, 2, 3}; + std::vector daysOfWeek (arr, arr + sizeof(arr) / sizeof(uint8_t)); + auto rrc = std::make_shared(0, 0, daysOfWeek); + uint8_t expectedVal = 7; + EXPECT_TRUE(rrc->GetRepeatDay() == expectedVal) << "repeatDays (1, 2, 3) should be 7"; +} + +/** + * @tc.number : initDaysOfWeek_00200 + * @tc.name : + * @tc.desc : test set daysOfWeek with edge value. + */ +HWTEST_F(ReminderRequestAlarmTest, initDaysOfWeek_00200, Function | SmallTest | Level1) +{ + uint8_t arr[] = {1, 7}; + std::vector daysOfWeek (arr, arr + sizeof(arr) / sizeof(uint8_t)); + auto rrc = std::make_shared(0, 0, daysOfWeek); + EXPECT_TRUE(rrc->GetRepeatDay() == 65) << "repeatDays (1, 12) should be 65"; +} + +/** + * @tc.number : initDaysOfWeek_00300 + * @tc.name : + * @tc.desc : test set daysOfWeek with duplicate value. + */ +HWTEST_F(ReminderRequestAlarmTest, initDaysOfWeek_00300, Function | SmallTest | Level1) +{ + uint8_t arr[] = {1, 1, 5, 5, 7, 7, 7}; + std::vector daysOfWeek (arr, arr + sizeof(arr) / sizeof(uint8_t)); + auto rrc = std::make_shared(0, 0, daysOfWeek); + EXPECT_TRUE(rrc->GetRepeatDay() == 81) << "repeatDays (1, 1, 5 12) should be 81"; +} + +/** + * @tc.number : initDaysOfWeek_00400 + * @tc.name : + * @tc.desc : test set daysOfWeek exceeding maximum length. + */ +HWTEST_F(ReminderRequestAlarmTest, initDaysOfWeek_00400, Function | SmallTest | Level1) +{ + uint8_t arr[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector daysOfWeek (arr, arr + sizeof(arr) / sizeof(uint8_t)); + try { + auto rrc = std::make_shared(0, 0, daysOfWeek); + EXPECT_TRUE(false) << "repeatDays exceeding maximum length should throw exception"; + } catch (const std::invalid_argument &e) { + EXPECT_TRUE(true); + } +} + +/** + * @tc.number : initDaysOfWeek_00500 + * @tc.name : + * @tc.desc : test set daysOfWeek with null value. + */ +HWTEST_F(ReminderRequestAlarmTest, initDaysOfWeek_00500, Function | SmallTest | Level1) +{ + uint8_t arr[] = {}; + std::vector daysOfWeek (arr, arr + sizeof(arr) / sizeof(uint8_t)); + auto rrc = std::make_shared(0, 0, daysOfWeek); + uint8_t expectedVal = 0; + EXPECT_TRUE(rrc->GetRepeatDay() == expectedVal) << "repeatDays () should be 0"; +} +} +} \ No newline at end of file diff --git a/frameworks/ans/native/test/unittest/reminder_request_test.cpp b/frameworks/ans/native/test/unittest/reminder_request_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0be99c93927a940a98839f25d30ed9969e19aa24 --- /dev/null +++ b/frameworks/ans/native/test/unittest/reminder_request_test.cpp @@ -0,0 +1,293 @@ +/* + * 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 + +#include "reminder_request.h" + +using namespace testing::ext; +namespace OHOS { +namespace Notification { +class ReminderRequestChild : public ReminderRequest { +public: + ReminderRequestChild() : ReminderRequest() {}; +}; + +class ReminderRequestTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {} + + static const uint8_t REMINDER_STATUS_SHOWING; +}; + +const uint8_t ReminderRequestTest::REMINDER_STATUS_SHOWING = 4; + +/** + * @tc.number : CanRemove_00100 + * @tc.name : + * @tc.desc : When reminder init, CanRemove should return true. + */ +HWTEST_F(ReminderRequestTest, CanRemove_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + EXPECT_TRUE(rrc->CanRemove()) << "When init, canRemove should be false"; +} + +/** + * @tc.number : CanRemove_00200 + * @tc.name : + * @tc.desc : When reminder is shown, CanRemove should return false. + */ +HWTEST_F(ReminderRequestTest, CanRemove_00200, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnShow(false, true); + EXPECT_FALSE(rrc->CanRemove()) << "When shown, canRemove should be false"; +} + +/** + * @tc.number : CanRemove_00300 + * @tc.name : + * @tc.desc : When reminder close, CanRemove should return true. + */ +HWTEST_F(ReminderRequestTest, CanRemove_00300, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnShow(false, true); + rrc->OnClose(false); + EXPECT_TRUE(rrc->CanRemove()) << "When reminder is expired and closed, can remove should be false"; +} + +/** + * @tc.number : CanRemove_00400 + * @tc.name : + * @tc.desc : When reminder is covered as same notification id, CanRemove should return true. + */ +HWTEST_F(ReminderRequestTest, CanRemove_00400, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnShow(false, true); + rrc->OnSameNotificationIdCovered(); + EXPECT_TRUE(rrc->CanRemove()) << "When reminder is expired and covered by \ + sameNotification id, can remove should be true"; +} + +/** + * @tc.number : StateCheck_00100 + * @tc.name : + * @tc.desc : When reminder init, state should be 0. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + EXPECT_EQ(rrc->GetState(), 0) << "When init, state should be 0"; +} + +/** + * @tc.number : StateCheck_00200 + * @tc.name : + * @tc.desc : When reminder close with param true, state REMINDER_STATUS_SHOWING should be unset. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00200, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnClose(true); + EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) == 0); +} + +/** + * @tc.number : StateCheck_00300 + * @tc.name : + * @tc.desc : When reminder close with param false, state REMINDER_STATUS_SHOWING should be unset. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00300, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnClose(false); + EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) == 0); +} + +/** + * @tc.number : StateCheck_00400 + * @tc.name : + * @tc.desc : When reminder is covered as same notification id, state REMINDER_STATUS_SHOWING should be unset. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00400, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnSameNotificationIdCovered(); + EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) == 0); +} + +/** + * @tc.number : StateCheck_00500 + * @tc.name : + * @tc.desc : When reminder is shown with param true,true, state REMINDER_STATUS_SHOWING should be set. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00500, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnShow(true, true); + EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) != 0); +} + +/** + * @tc.number : StateCheck_00600 + * @tc.name : + * @tc.desc : When reminder is shown with param false,true, state REMINDER_STATUS_SHOWING should be set. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00600, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->OnShow(false, true); + EXPECT_TRUE((rrc->GetState() & ReminderRequestTest::REMINDER_STATUS_SHOWING) != 0); +} + +/** + * @tc.number : StateCheck_00700 + * @tc.name : + * @tc.desc : When reminder is shown with param true,false, state REMINDER_STATUS_SHOWING should not change. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00700, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + uint8_t stateBefore = rrc->GetState(); + rrc->OnShow(true, false); + EXPECT_EQ(rrc->GetState(), stateBefore); +} + +/** + * @tc.number : StateCheck_00800 + * @tc.name : + * @tc.desc : When reminder is shown with param false,false, state REMINDER_STATUS_SHOWING should be unset. + */ +HWTEST_F(ReminderRequestTest, StateCheck_00800, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + uint8_t stateBefore = rrc->GetState(); + rrc->OnShow(false, false); + EXPECT_EQ(rrc->GetState(), stateBefore); +} + +/** + * @tc.number : initReminderId_00100 + * @tc.name : + * @tc.desc : When reminder create successfully, system should assign unique id to reminder. + */ +HWTEST_F(ReminderRequestTest, initReminderId_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + rrc->InitReminderId(); + int32_t reminderIdBefore = rrc->GetReminderId(); + rrc->InitReminderId(); + int32_t reminderIdAfter = rrc->GetReminderId(); + EXPECT_EQ((reminderIdAfter - reminderIdBefore), 1); +} + +/** + * @tc.number : setContent_00100 + * @tc.name : + * @tc.desc : Test SetContent with normal parameters. + */ +HWTEST_F(ReminderRequestTest, setContent_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + std::string content = "this is normal content"; + rrc->SetContent(content); + EXPECT_EQ(rrc->GetContent(), content); +} + +/** + * @tc.number : setContent_00200 + * @tc.name : + * @tc.desc : Test SetContent parameters with special characters. + */ +HWTEST_F(ReminderRequestTest, setContent_00200, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + std::string content = "this is content with special characters: ~!@#$%^&*()-+"; + rrc->SetContent(content); + EXPECT_EQ(rrc->GetContent(), content); +} + +/** + * @tc.number : setExpiredContent_00100 + * @tc.name : + * @tc.desc : Test SetExpiredContent with normal parameters. + */ +HWTEST_F(ReminderRequestTest, setExpiredContent_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + std::string content = "this is normal content"; + rrc->SetExpiredContent(content); + EXPECT_EQ(rrc->GetExpiredContent(), content); +} + +/** + * @tc.number : setExpiredContent_00200 + * @tc.name : + * @tc.desc : Test SetExpiredContent with special characters. + */ +HWTEST_F(ReminderRequestTest, setExpiredContent_00200, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + std::string content = "this is content with special characters: ~!@#$%^&*()-+"; + rrc->SetExpiredContent(content); + EXPECT_EQ(rrc->GetExpiredContent(), content); +} + +/** + * @tc.number : setTitle_00100 + * @tc.name : + * @tc.desc : Test SetTitle with normal parameters. + */ +HWTEST_F(ReminderRequestTest, setTitle_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + std::string content = "this is normal content"; + rrc->SetTitle(content); + EXPECT_EQ(rrc->GetTitle(), content); +} + +/** + * @tc.number : setTitle_00200 + * @tc.name : + * @tc.desc : Test SetTitle with special characters. + */ +HWTEST_F(ReminderRequestTest, setTitle_00200, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + std::string content = "this is content with special characters: ~!@#$%^&*()-+"; + rrc->SetTitle(content); + EXPECT_EQ(rrc->GetTitle(), content); +} + +/** + * @tc.number : setNotificationId_00100 + * @tc.name : + * @tc.desc : Test SetNotificationId parameters. + */ +HWTEST_F(ReminderRequestTest, setNotificationId_00100, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(); + int32_t notificationId = 0; + rrc->SetNotificationId(notificationId); + EXPECT_EQ(rrc->GetNotificationId(), notificationId); +} +} +} \ No newline at end of file diff --git a/frameworks/ans/native/test/unittest/reminder_request_timer_test.cpp b/frameworks/ans/native/test/unittest/reminder_request_timer_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bd1e48e76d9445470871ec4d8be52ce463b9d75 --- /dev/null +++ b/frameworks/ans/native/test/unittest/reminder_request_timer_test.cpp @@ -0,0 +1,87 @@ +/* + * 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 + +#include "ans_log_wrapper.h" +#include "reminder_request_timer.h" +#include "reminder_helper.h" + +using namespace testing::ext; +namespace OHOS { +namespace Notification { +class ReminderRequestTimerTest : public testing::Test { +public: + static void SetUpTestCase() + { + ReminderHelper::CancelAllReminders(); + } + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() + { + ReminderHelper::CancelAllReminders(); + } +}; + +/** + * @tc.number : initCountDownTime_00100 + * @tc.name : + * @tc.desc : set countDownTime = 0 should throw exception. + */ +HWTEST_F(ReminderRequestTimerTest, initCountDownTime_00100, Function | SmallTest | Level1) +{ + try { + auto rrc = std::make_shared(0); + EXPECT_TRUE(false) << "countDownTime < 0 should throw exception."; + } catch (const std::invalid_argument &e) { + ANSR_LOGI("countDownTime < 0 throw exception."); + } +} + +/** + * @tc.number : initCountDownTime_00200 + * @tc.name : + * @tc.desc : set countDownTime > (UINT64_MAX / 1000) should throw exception. + */ +HWTEST_F(ReminderRequestTimerTest, initCountDownTime_00200, Function | SmallTest | Level1) +{ + try { + auto rrc = std::make_shared(UINT64_MAX / 1000); + EXPECT_TRUE(false) << "countDownTime >= (UINT64_MAX / 1000) should throw exception."; + } catch (const std::invalid_argument &e) { + ANSR_LOGI("countDownTime > (UINT64_MAX / 1000) throw exception."); + } +} + + +/** + * @tc.number : initCountDownTime_00300 + * @tc.name : + * @tc.desc : set countDownTime with normal value. + */ +HWTEST_F(ReminderRequestTimerTest, initCountDownTime_00300, Function | SmallTest | Level1) +{ + auto rrc = std::make_shared(1); + EXPECT_TRUE(rrc->GetInitInfo() == 1) << "countDownTime is not 1"; + + auto rrc2 = std::make_shared(10); + EXPECT_TRUE(rrc2->GetInitInfo() == 10) << "countDownTime is not 10"; + + auto rrc3 = std::make_shared(100); + EXPECT_TRUE(rrc3->GetInitInfo() == 100) << "countDownTime is not 1"; +} +} +} \ No newline at end of file diff --git a/interfaces/BUILD.gn b/interfaces/BUILD.gn index 2c3010f9cc0e8536af768dddea767ee83903e2ee..d5d17329a3a911b355edd4323a28161df69bd8d0 100644 --- a/interfaces/BUILD.gn +++ b/interfaces/BUILD.gn @@ -14,6 +14,7 @@ group("interfaces_target") { deps = [ "kits/napi/ans:notification", + "kits/napi/ans/src/reminder:reminderagent", "kits/napi/wantagent:wantagent", ] } diff --git a/interfaces/innerkits/ans/native/include/reminder_helper.h b/interfaces/innerkits/ans/native/include/reminder_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..0d7f34d8880c0a3ee6fec2c2810703f5256b6473 --- /dev/null +++ b/interfaces/innerkits/ans/native/include/reminder_helper.h @@ -0,0 +1,106 @@ +/* + * 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_KITS_NATIVE_INCLUDE_REMINDER_HELPER_H +#define BASE_NOTIFICATION_ANS_STANDARD_KITS_NATIVE_INCLUDE_REMINDER_HELPER_H + +#include + +#include "notification_slot.h" +#include "reminder_request.h" + +namespace OHOS { +namespace Notification { +class ReminderHelper { +public: + /** + * Publishes a scheduled reminder. + * + * Third-party applications can call this method to publish a scheduled reminder. After this method is called, + * the timing and pop-up notification functions of the calling application will be performed by the system service + * agent in the background, even when the application is frozen or exits. You can call the + * ReminderRequest::SetWantAgentInfo(WantAgentInfo wantAgentInfo) method to specify whether to start the + * application after the pop-up notification is taped. + * + * The background agent maintains an ordered list of reminders for all third-party applications. The list is + * updated based on the scheduled trigger time of each reminder. The system starts only one most recent scheduled + * reminder at a time. If a reminder with a more recent trigger time is added, the new scheduled reminder will + * be put on top of the list. The next reminder is triggered only after the current reminder is complete. + * + * @note One application can create a maximum of 30 valid reminders, and the total number of valid reminders + * in the system cannot exceed 2000. The minimum snooze interval for a reminder is 5 minutes. + * + * @param reminder Indicates the reminder instance to publish. This parameter cannot be null. Otherwise, + * an exception will be thrown due to invalid parameters, causing the application to crash. + * @return Returns publish reminder result. + * Reminder id will be set with a number >= 0 if publishing the reminder successfully, Otherwise + * reminder id is -1. You can call reminder.GetReminderId() to get the reminder id. + */ + static ErrCode PublishReminder(ReminderRequest &reminder); + + /** + * Cancels a specified reminder. + * + * @param reminderId Indicates the ID of the reminder instace to cancel. + * @return Returns cancel reminder result. + */ + static ErrCode CancelReminder(const int32_t reminderId); + + /** + * Cancels all reminders of current third part application. + * + * @return Returns cancel all reminders result. + */ + static ErrCode CancelAllReminders(); + + /** + * Obtains all valid reminder notifications set by the current application, namely, the reminders that will + * still be triggered later. If a reminder will never be triggered again, it is not considered a valid reminder. + * + * @param[out] validReminders Indicates an initial vector to recieve the result. + * @return Returns an array list containing all valid reminder notifications set by the current application. + */ + static ErrCode GetValidReminders(std::vector> &validReminders); + + /** + * Creates a NotificationSlot. + * + * After a notification slot is created by using this method, only the name and description of the notification + * slot can be changed. Changes to the other attributes, such as the vibration status and notification tone, + * will no longer take effect. + * + * You can call the ReminderRequest#setSlotId(String) method to bind the slot for publishing a reminder. + * When the application is uninstalled, all notification slots related to the application will be deleted. + * + * @param slot Indicates the NotificationSlot instance to add. + * @return Returns add notification slot result. + */ + static ErrCode AddNotificationSlot(const NotificationSlot &slot); + + /** + * Removes a NotificationSlot instance used by the reminder. + * + * @param slotType Indicates the type of the slot, which is set when calling AddNotificationSlot to add a slot. + * @return Returns remove notification slot result. + */ + static ErrCode RemoveNotificationSlot(const NotificationConstant::SlotType &slotType); + +private: + static bool CheckPermission(); +}; +} // namespace Reminder +} // namespace OHOS + +#endif // BASE_NOTIFICATION_ANS_STANDARD_KITS_NATIVE_INCLUDE_REMINDER_HELPER_H \ No newline at end of file diff --git a/interfaces/innerkits/ans/native/include/reminder_request.h b/interfaces/innerkits/ans/native/include/reminder_request.h new file mode 100644 index 0000000000000000000000000000000000000000..87445ac4c5c6d2a58c47a3773f6bc1d932958581 --- /dev/null +++ b/interfaces/innerkits/ans/native/include/reminder_request.h @@ -0,0 +1,444 @@ +/* + * 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_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_H + +#include +#include + +#include "notification_constant.h" +#include "notification_request.h" + +namespace OHOS { +namespace Notification { +class ReminderRequest : public Parcelable { +public: + /** + * @brief Supported reminder type. + */ + enum class ReminderType : uint8_t { + /** + * Indicates the classification of reminder for timer. + */ + TIMER, + + /** + * Indicates the classification of reminder for calendar. + */ + CALENDAR, + + /** + * Indicates the classification of reminder for alarm. + */ + ALARM, + INVALID + }; + + /** + * @brief Supported action button type. + */ + enum class ActionButtonType : uint8_t { + /** + * @brief Indicates that this action button is used to close reminder's notfication. + * It always works well, whether the application is running at the time. + * + */ + CLOSE, + + /** + * @brief Indicates that this action button is used to snooze reminder. + * It always work well, whether the application is running at the time. + * + */ + SNOOZE, + INVALID + }; + + /** + * @brief Supported notification update type. + */ + enum class UpdateNotificationType : uint8_t { + COMMON, + ACTION_BUTTON, + REMOVAL_WANT_AGENT, + CONTENT + }; + + /** + * @brief Attributes of action button. + */ + struct ActionButtonInfo { + /** + * Type of the button. + */ + ActionButtonType type; + + /** + * Content show on the button. + */ + std::string title = ""; + }; + + /** + * @brief Want agent information. Indicates the package and the ability to switch to. + */ + struct WantAgentInfo { + std::string pkgName = ""; + std::string abilityName = ""; + }; + + /** + * @brief Copy construct from an exist reminder. + * + * @param Indicates the exist reminder. + */ + explicit ReminderRequest(const ReminderRequest &other); + ReminderRequest& operator = (const ReminderRequest &other); + virtual ~ReminderRequest() {}; + + /** + * @brief Marshal a NotificationRequest object into a Parcel. + * + * @param parcel the object into the parcel + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Unmarshal object from a Parcel. + * + * @return the NotificationRequest + */ + static ReminderRequest *Unmarshalling(Parcel &parcel); + virtual bool ReadFromParcel(Parcel &parcel); + + /** + * @brief If the reminder is showing on the notification panel, it should not be removed automatically. + * + * @return true if it can be removed automatically. + */ + bool CanRemove(); + + /** + * @brief Obtains all the information of the reminder. + * + * @return Information of the reminder. + */ + std::string Dump() const; + + /** + * @brief Obtains the configured action buttons. + * + * @return map of action buttons. + */ + std::map GetActionButtons() const; + + /** + * @brief Obtains the configured content. + * + * @return content text. + */ + std::string GetContent() const; + + /** + * @brief Obtains the configured expired content. + * + * @return expired content text. + */ + std::string GetExpiredContent() const; + + /** + * @brief Obtains notification id. + * + * @return notification id. + */ + int32_t GetNotificationId() const; + + /** + * @brief Obtains notification request. + * + * @return notification request instance. + */ + sptr GetNotificationRequest() const; + + /** + * @brief Obtains reminder id. + * + * @return reminder id. + */ + int32_t GetReminderId() const; + + /** + * @brief Obtains reminder type. + * + * @return reminder type. + */ + ReminderType GetReminderType() const; + + /** + * @brief Obtains slot type. + * + * @return slot type. + */ + NotificationConstant::SlotType GetSlotType() const; + + uint8_t GetState() const; + + /** + * @brief Obtains title. + * + * @return title. + */ + std::string GetTitle() const; + + /** + * @brief Obtains trigger time in milli. + * + * @return trigger time. + */ + uint64_t GetTriggerTimeInMilli() const; + + /** + * @brief Obtains want agent information. + * + * @return want agent information. + */ + std::shared_ptr GetWantAgentInfo() const; + + /** + * @brief Inits reminder id when publish reminder success. + * Assign a unique reminder id for each reminder. + */ + void InitReminderId(); + + /** + * @brief Check the reminder is expired or not. + * + * @return true is the reminder is expired. + */ + bool IsExpired() const; + + /** + * @brief Check the reminder is showing on the panel. + * + * @return true if the reminder is showing on the panel. + */ + bool IsShowing() const; + + /** + * @brief Close the reminder by manual. + * + * @param updateNext Whether to update to next reminder. + */ + void OnClose(bool updateNext); + + /** + * @brief When date/time change, reminder need to refresh next trigger time. + * + * @return true if need to show reminder immediately. + */ + virtual bool OnDateTimeChange(); + + /** + * When shown notification is covered by a new notification with the same id, we should remove + * the state of showing, so that the reminder can be removed automatically when it is expired. + */ + void OnSameNotificationIdCovered(); + + /** + * @brief Show the reminder on panel. TriggerTime will be updated to next. + * + * @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); + + /** + * @brief When timezone change, reminder need to refresh next trigger time. + * + * @return true if need to show reminder immediately. + */ + virtual bool OnTimeZoneChange(); + + /** + * @brief Sets action button. + * + * @param title Indicates the title of the button. + * @param type Indicates the type of the button. + * @return Current reminder self. + */ + ReminderRequest& SetActionButton(const std::string &title, const ActionButtonType &type); + + /** + * @brief Sets reminder content. + * + * @param content Indicates content text. + * @return Current reminder self. + */ + ReminderRequest& SetContent(const std::string &content); + + /** + * @brief Sets reminder is expired or not. + * + * @param isExpired Indicates the reminder is expired or not. + */ + void SetExpired(bool isExpired); + + /** + * @brief Sets expired content. + * + * @param expiredContent Indicates expired content. + * @return Current reminder self. + */ + ReminderRequest& SetExpiredContent(const std::string &expiredContent); + + /** + * @brief Sets notification id. + * + * @param notificationId Indicates notification id. + * @return Current reminder self. + */ + ReminderRequest& SetNotificationId(int32_t notificationId); + + /** + * @brief Sets reminder id. + * + * @param reminderId Indicates reminder id. + */ + void SetReminderId(int32_t reminderId); + + /** + * @brief Sets slot type. + * + * @param slotType Indicates slot type. + * @return Current reminder self. + */ + ReminderRequest& SetSlotType(const NotificationConstant::SlotType &slotType); + + /** + * @brief Sets title. + * + * @param title Indicates title. + * @return Current reminder self. + */ + ReminderRequest& SetTitle(const std::string &title); + + /** + * @brief Sets trigger time. + * + * @param triggerTimeInMilli Indicates trigger time in milli. + */ + void SetTriggerTimeInMilli(uint64_t triggerTimeInMilli); + + /** + * @brief Sets want agent information. + * + * @param wantAgentInfo Indicates want agent information. + * @return Current reminder self. + */ + ReminderRequest& SetWantAgentInfo(const std::shared_ptr &wantAgentInfo); + + /** + * @brief Updates {@link triggerTimeInMilli_} to next. + * @note If next trigger time not exist, {@link isExpired_} flag will be set with true. + * + * @return true if next trigger time exist and set success. + */ + virtual bool UpdateNextReminder(); + + /** + * @brief Update notification attibutes. + * + * Some attributes need to be updated after the reminder published or before the notification publish. + * For example, action button should not init until the reminder is published successfully, as the reminder id is + * assigned after that. + * + * @param type Indicates the update type. + * @param extra Indicates the extra content. + */ + void UpdateNotificationRequest(UpdateNotificationType type, std::string extra); + + static int32_t GLOBAL_ID; + static const uint64_t INVALID_LONG_VALUE; + static const uint16_t MILLI_SECONDS; + static const uint16_t SAME_TIME_DISTINGUISH_MILLISECONDS; + static const std::string NOTIFICATION_LABEL; + + /** + * @brief Show the reminder with a notification. + */ + static const std::string REMINDER_EVENT_ALARM_ALERT; + + /** + * @brief Close the reminder when click the close button of notification. + */ + static const std::string REMINDER_EVENT_CLOSE_ALERT; + + /** + * @brief Snooze the reminder when click the snooze button of notification. + */ + static const std::string REMINDER_EVENT_SNOOZE_ALERT; + + /** + * @brief Used to control ring duration. + */ + static const std::string REMINDER_EVENT_ALERT_TIMEOUT; + + /** + * @brief Update the reminder when remove notification from the systemUI. + */ + static const std::string REMINDER_EVENT_REMOVE_NOTIFICATION; + static const std::string PARAM_REMINDER_ID; + +protected: + ReminderRequest(); + explicit ReminderRequest(ReminderType reminderType); + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const + { + return INVALID_LONG_VALUE; + } + +private: + void AddActionButtons(); + void AddRemovalWantAgent(); + 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 SetState(bool deSet, const uint8_t newState, std::string function); + void SetWantAgent(); + void UpdateNotificationCommon(); + + static const uint8_t REMINDER_STATUS_INACTIVE; + static const uint8_t REMINDER_STATUS_SHOWING; + + std::string content_ {}; + std::string expiredContent_ {}; + std::string title_ {}; + bool isExpired_ {false}; + uint8_t state_ {0}; + int32_t notificationId_ {0}; + int32_t reminderId_ {-1}; + uint64_t triggerTimeInMilli_ {0}; + ReminderType reminderType_ {ReminderType::INVALID}; + NotificationConstant::SlotType slotType_ {NotificationConstant::SlotType::SOCIAL_COMMUNICATION}; + sptr notificationRequest_ = nullptr; + std::shared_ptr wantAgentInfo_ = nullptr; + std::map actionButtonMap_ {}; +}; +} // namespace Reminder +} // namespace OHOS + +#endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_H \ No newline at end of file diff --git a/interfaces/innerkits/ans/native/include/reminder_request_alarm.h b/interfaces/innerkits/ans/native/include/reminder_request_alarm.h new file mode 100644 index 0000000000000000000000000000000000000000..e05550d84071017d574b4622b643bdc4f827306f --- /dev/null +++ b/interfaces/innerkits/ans/native/include/reminder_request_alarm.h @@ -0,0 +1,153 @@ +/* + * 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_ALARM_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_ALARM_H + +#include "reminder_request.h" + +#include + +namespace OHOS { +namespace Notification { +class ReminderRequestAlarm : public ReminderRequest { +public: + /** + * @brief A {@link ReminderRequest} child class used for creating reminders of alarm clocks. + * You can use this class to publish alarm reminders at a specified time (accurate to minute) on a + * particular day or on particular days every week. + * + * @note The params must meet the following conditions, + * otherwise the application may crash due to an illegal parameter exception. + * + * @param hour The value must between [0, 23]. + * @param minute The value must between [0, 59]. + * @param daysOfWeek The value must between [1, 7], and the length of array can not be greater than 7. + * + * @see ReminderRequestTimer + */ + ReminderRequestAlarm(uint8_t hour, uint8_t minute, std::vector daysOfWeek); + + /** + * @brief Copy construct from an exist reminder. + * + * @param Indicates the exist alarm reminder. + */ + explicit ReminderRequestAlarm(const ReminderRequestAlarm &other); + ReminderRequestAlarm& operator = (const ReminderRequestAlarm &other); + ~ReminderRequestAlarm() {}; + + /** + * Obtains the repeat days vector. + * + * @return vector of repeat days. + */ + std::vector GetDaysOfWeek() const; + + /** + * @brief Obtains the setted {@link hour_}. + * + * @return setted hour. + */ + uint8_t GetHour() const; + + /** + * @brief Obtains the setted {@link minute_}. + * + * @return setted minute. + */ + uint8_t GetMinute() const; + uint8_t GetRepeatDay() 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 ReminderRequestAlarm *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; + +protected: + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const override; + +private: + ReminderRequestAlarm() : ReminderRequest() {}; + void CheckParamValid() const; + + /** + * Obtains the next trigger time. + * + * @param forceToGetNext Indicates whether force to get next reminder. + * When set the alarm firstly, you should set force with true, so if repeat information + * is not set, and the target time is overdue, the reminder will be set to next day. + * When change the time manually by user, you should set force with false, so if repeat + * information is not set, and target time is overdue, the reminder will not be set to + * next day. + * @return next trigger time in milli. + */ + uint64_t GetNextTriggerTime(bool forceToGetNext) const; + + /** + * Judge is it the repeat day setted by user or not. + * + * @param day Indicates the day of week. + * @return true if it is a repeat day. + */ + bool IsRepeatDay(int day) const; + void SetDaysOfWeek(bool set, std::vector daysOfWeek); + + /** + * Obtains the next day interval if it is a week repeat alarm. + * + * @param now Indicates current time. + * @param now Indicatet target time. + * @return next day interval. Returns {@link INVALID_INT_VALUE} if it is not a week repeat alarm. + */ + int8_t GetNextAlarm(const time_t now, const time_t target) const; + + static const uint8_t DAYS_PER_WEEK; + static const uint8_t MONDAY; + static const uint8_t SUNDAY; + static const uint8_t HOURS_PER_DAY; + static const uint16_t SECONDS_PER_HOUR; + static const uint8_t MINUTES_PER_HOUR; + static const int8_t INVALID_INT_VALUE; + + uint8_t hour_ = {0}; + uint8_t minute_ = {0}; + uint8_t repeatDays_ = {0}; +}; +} // namespace Notification +} // namespace OHOS + +#endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_ALARM_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 new file mode 100644 index 0000000000000000000000000000000000000000..03705509c9da7c9702e17bb3cf141ae194b1cd16 --- /dev/null +++ b/interfaces/innerkits/ans/native/include/reminder_request_timer.h @@ -0,0 +1,77 @@ +/* + * 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_TIMER_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_TIMER_H + +#include "reminder_request.h" + +namespace OHOS { +namespace Notification { +class ReminderRequestTimer : public ReminderRequest { +public: + /** + * A constructor used to create a ReminderRequestTimer instance. The countdown timer reminder + * will be triggered after a specified duration. + * + * @note The input parameter must be larger than 0 and less than UINT64_MAX/1000, + * otherwise, the application may crash due to an illegal parameter exception. + * + * @param countDownTimeInSeconds Indicates the duration after which this timer reminder will be triggered. + */ + ReminderRequestTimer(uint64_t countDownTimeInSeconds); + + /** + * @brief Copy construct from an exist reminder. + * + * @param Indicates the exist reminder. + */ + explicit ReminderRequestTimer(const ReminderRequestTimer &other); + ReminderRequestTimer& operator = (const ReminderRequestTimer &other); + ~ReminderRequestTimer() {}; + + uint64_t GetInitInfo() const; + virtual bool OnDateTimeChange() override; + virtual bool OnTimeZoneChange() override; + virtual bool UpdateNextReminder() override; + + /** + * Marshal a NotificationRequest object into a Parcel. + * @param parcel the object into the parcel + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * Unmarshal object from a Parcel. + * @return the NotificationRequest + */ + static ReminderRequestTimer *Unmarshalling(Parcel &parcel); + + bool ReadFromParcel(Parcel &parcel) override; + +protected: + virtual uint64_t PreGetNextTriggerTimeIgnoreSnooze(bool forceToGetNext) const override; + +private: + ReminderRequestTimer() {}; + void CheckParamsValid(const uint64_t countDownTimeInSeconds) const; + void UpdateTimeInfo(const std::string description); + uint64_t countDownTimeInSeconds_ {0}; + uint64_t firstRealTimeInMilliSeconds_ {-1}; + uint64_t whenToChangeSysTime_ {-1}; +}; +} // namespace Reminder +} // namespace OHOS +#endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_REQUEST_TIMER_H \ No newline at end of file diff --git a/interfaces/kits/js/@ohos.reminderAgent.d.ts b/interfaces/kits/js/@ohos.reminderAgent.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..96c26e2dce021bf44c655890cba66354e5538ab0 --- /dev/null +++ b/interfaces/kits/js/@ohos.reminderAgent.d.ts @@ -0,0 +1,295 @@ +/* + * 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. + */ + +import { AsyncCallback } from './basic'; +import notification from './@ohos.notification'; +import { NotificationSlot } from './notification/notificationSlot'; + +/** + * Providers static methods for managing reminders, including publishing or canceling a reminder. + * adding or removing a notification slot, and obtaining or cancelling all reminders of the current application. + * + * @since 7 + * @sysCap Agent-Powered Reminder. + * @import reminderAgent from '@ohos.reminderAgent'; + */ +declare namespace reminderAgent { + /** + * Publishes a scheduled reminder. + * + * @since 7 + * @sysCap Publishes an agent-powered reminder. + * @permission ohos.permission.PUBLISH_AGENT_REMINDER + * @param reminderReq Indicates the reminder instance to publish. + * @param callback Indicates the callback function. + * @returns reminder id. + */ + function publishReminder(reminderReq: ReminderRequest, callback: AsyncCallback): void; + function publishReminder(reminderReq: ReminderRequest): Promise; + + /** + * Cancels a reminder. + * + * @since 7 + * @sysCap Cancels the reminder with the specified ID. + * @param reminderId Indicates the reminder id. + * @param callback Indicates the callback function. + */ + function cancelReminder(reminderId: number, callback: AsyncCallback): void; + function cancelReminder(reminderId: number): Promise; + + /** + * Obtains all the valid reminders of current application. + * + * @since 7 + * @sysCap Obtains all valid (not yet expired) remindeers set by the current application. + * @param callback Indicates the callback function. + */ + function getValidReminders(callback: AsyncCallback>): void; + function getValidReminders(): Promise>; + + /** + * Cancels all the reminders of current application. + * + * @since 7 + * @sysCap Cancels all the reminders set by the current application. + * @param callback Indicates the callback function. + */ + function cancelAllReminders(callback: AsyncCallback): void; + function cancelAllReminders(): Promise; + + /** + * Add notification slot. + * + * @since 7 + * @sysCap Adds a reminder notification slot. + * @param slot Indicates the slot. + * @param callback Indicates the callback function. + */ + function addNotificationSlot(slot: NotificationSlot, callback: AsyncCallback): void; + function addNotificationSlot(slot: NotificationSlot): Promise; + + /** + * Deletes a created notification slot based on the slot type. + * + * @since 7 + * @sysCap Removes a notification slot instance of a specified type. + * @param slotType Indicates the type of the slot. + * @param callback Indicates the callback function. + */ + function removeNotificationSlot(slotType: notification.SlotType, callback: AsyncCallback): void; + function removeNotificationSlot(slotType: notification.SlotType): Promise; + + /** + * Declares action button type. + * + * @since 7 + * @sysCap Define action button type. + */ + export enum ActionButtonType { + /** + * Button for closing the reminder. + * @since 7 + * @sysCap Agent-Powered reminder. + */ + ACTION_BUTTON_TYPE_CLOSE = 0, + + /** + * Button for snoozing the reminder. + * @since 7 + * @sysCap Agent-Powered reminder. + */ + ACTION_BUTTON_TYPE_SNOOZE = 1 + } + + /** + * Declares reminder type. + * + * @since 7 + * @sysCap Define reminder type. + */ + export enum ReminderType { + /** + * Countdown reminder. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + REMINDER_TYPE_TIMER = 0, + + /** + * Calendar reminder. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + REMINDER_TYPE_CALENDAR = 1, + + /** + * Alarm reminder. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + REMINDER_TYPE_ALARM = 2 + } + + /** + * Action button information. The button will show on displayed reminder. + * + * @since 7 + * @sysCap Define action button object. + */ + interface ActionButton { + /** + * Text on the button. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + title: string; + + /** + * Button type. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + type: ActionButtonType; + } + + /** + * Want agent information. + * It will switch to target ability when you click the displayed reminder. + * + * @since 7 + * @sysCap Define want agent object. + */ + interface WantAgent { + /** + * Name of the package redirected to when the reminder notification is clicked. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + pkgName: string; + + /** + * Name of the ability that is redirected to when the reminder notification is clicked. + * @since 7 + * @sysCap Agent-Powered Reminder. + */ + abilityName: string; + } + + /** + * Reminder Common information. + * + * @since 7 + * @sysCap Define reminder request object. + */ + interface ReminderRequest { + /** + * Type of the reminder. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + reminderType: ReminderType; + + /** + * Action button displayed on the reminder notification. + * (The parameter is optional. Up to two buttons are supported). + * @since 7 + * @sysCap Agent-Powered Reminder + */ + actionButton?: [ActionButton?, ActionButton?]; + + /** + * Information about the ability that is redirected to when the notification is clicked. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + wantAgent?: WantAgent; + + /** + * Reminder title. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + title?: string; + + /** + * Reminder content. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + content?: string; + + /** + * Content to be displayed when the reminder is snoozing. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + expiredContent?: string; + + /** + * notification id. If there are reminders with the same ID, the later one will overwrite the earlier one. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + notificationId?: number; + + /** + * Type of the slot used by the reminder. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + slotType?: notification.SlotType; + } + + /** + * Alarm reminder information. + * + * @since 7 + * @sysCap Define alarm reminder object. + */ + interface ReminderRequestAlarm extends ReminderRequest { + /** + * Hour portion of the reminder time. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + hour: number; + + /** + * minute portion of the remidner time. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + minute: number; + + /** + * Days of a week when the reminder repeates. + * @since 7 + * @sysCap Agent-Powered Reminder + */ + daysOfWeek?: Array; + } + + /** + * CountDown reminder information. + * + * @since 7 + * @sysCap Define count down timer reminder object. + */ + interface ReminderRequestTimer extends ReminderRequest { + triggerTimeInSeconds: number; + } +} +export default reminderAgent; diff --git a/interfaces/kits/napi/ans/include/reminder/native_module.h b/interfaces/kits/napi/ans/include/reminder/native_module.h new file mode 100644 index 0000000000000000000000000000000000000000..b720a915fad114195f70ccf15cbafd02b4a741f1 --- /dev/null +++ b/interfaces/kits/napi/ans/include/reminder/native_module.h @@ -0,0 +1,39 @@ +/* + * 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_KITS_NAPI_INCLUDE_REMINDER_NATIVE_MODULE_H +#define BASE_NOTIFICATION_ANS_STANDARD_KITS_NAPI_INCLUDE_REMINDER_NATIVE_MODULE_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace ReminderAgentNapi { +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((constructor)) void RegisterModule(void); +napi_value ConstantInit(napi_env env, napi_value exports); +napi_value ReminderAgentInit(napi_env env, napi_value exports); + +static napi_value Init(napi_env env, napi_value exports); + +#ifdef __cplusplus +} +#endif +} // namespace OHOS +} // namespace ReminderAgentNapi + +#endif // BASE_NOTIFICATION_ANS_STANDARD_KITS_NAPI_INCLUDE_REMINDER_NATIVE_MODULE_H \ No newline at end of file diff --git a/interfaces/kits/napi/ans/include/reminder/publish.h b/interfaces/kits/napi/ans/include/reminder/publish.h new file mode 100644 index 0000000000000000000000000000000000000000..bb312474615cbf8a898af5f8983d892fa18bf37d --- /dev/null +++ b/interfaces/kits/napi/ans/include/reminder/publish.h @@ -0,0 +1,60 @@ +/* + * 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_KITS_NAPI_INCLUDE_REMINDER_PUBLISH_H +#define BASE_NOTIFICATION_ANS_STANDARD_KITS_NAPI_INCLUDE_REMINDER_PUBLISH_H + +#include "reminder/reminder_common.h" + +namespace OHOS { +namespace ReminderAgentNapi { +/** + * @brief Cancels a reminder. + * + * @param env Indicates the context. + * @param info Indicates the opaque datatype about the context. + * @return opaque pointer that is used to represent a JavaScript value + */ +napi_value CancelReminder(napi_env env, napi_callback_info info); + +/** + * @brief Cancels all reminders of current bundle. + * + * @param env Indicates the context. + * @param info Indicates the opaque datatype about the context. + * @return opaque pointer that is used to represent a JavaScript value + */ +napi_value CancelAllReminders(napi_env env, napi_callback_info info); + +/** + * @brief Obtains all reminders of current bundle. + * + * @param env Indicates the context. + * @param info Indicates the opaque datatype about the context. + * @return opaque pointer that is used to represent a JavaScript value + */ +napi_value GetValidReminders(napi_env env, napi_callback_info info); + +/** + * @brief Publishes a reminder. + * + * @param env Indicates the context. + * @param info Indicates the opaque datatype about the context. + * @return opaque pointer that is used to represent a JavaScript value + */ +napi_value PublishReminder(napi_env env, napi_callback_info info); +} // namespace ReminderAgentNapi +} // namespace OHOS + +#endif // BASE_NOTIFICATION_ANS_STANDARD_KITS_NAPI_INCLUDE_REMINDER_PUBLISH_H diff --git a/interfaces/kits/napi/ans/include/reminder/reminder_common.h b/interfaces/kits/napi/ans/include/reminder/reminder_common.h new file mode 100644 index 0000000000000000000000000000000000000000..0f9b9e057ceacfacdd74ca6a15bb5a24e71dd99e --- /dev/null +++ b/interfaces/kits/napi/ans/include/reminder/reminder_common.h @@ -0,0 +1,97 @@ +/* + * 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_KITS_NAPI_INCLUDE_REMINDER_COMMON_H +#define BASE_NOTIFICATION_ANS_STANDARD_KITS_NAPI_INCLUDE_REMINDER_COMMON_H + +#include "ans_log_wrapper.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "reminder_helper.h" +#include "reminder_request.h" + +namespace OHOS { +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* CONTENT = "content"; +const char* EXPIRED_CONTENT = "expiredContent"; +const char* NOTIFICATION_ID = "notificationId"; +const char* SLOT_TYPE = "slotType"; +} + +class ReminderCommon { + ReminderCommon(); + ~ReminderCommon(); + ReminderCommon(ReminderCommon &other) = delete; + ReminderCommon& operator = (const ReminderCommon &other) = delete; + +public: + static napi_value GetReminderRequest( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder); + + static bool GetStringUtf8(const napi_env &env, const napi_value &value, + 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); + + static bool GetInt64(const napi_env &env, const napi_value &value, + const char* propertyName, int64_t& propertyVal); + + static bool GetObject(const napi_env &env, const napi_value &value, + 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 GetPropertyValIfExist(const napi_env &env, const napi_value &value, + const char* propertyName, napi_value& propertyVal); + + 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( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder); + + 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 ParseDaysOfWeek( + const napi_env &env, const napi_value &value, std::vector &daysOfWeek); +}; +} // namespace OHOS +} // namespace ReminderAgentNapi + +#endif // BASE_NOTIFICATION_ANS_STANDARD_KITS_NAPI_INCLUDE_REMINDER_COMMON_H diff --git a/interfaces/kits/napi/ans/src/reminder/BUILD.gn b/interfaces/kits/napi/ans/src/reminder/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..19d5a8cd3c55ce22aeba1ef8579a1926df275397 --- /dev/null +++ b/interfaces/kits/napi/ans/src/reminder/BUILD.gn @@ -0,0 +1,81 @@ +# 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. + +import("//base/notification/ans_standard/notification.gni") +import("//build/ohos.gni") + +cflags = [] + +config("native_module_config") { + visibility = [ ":*" ] + + include_dirs = [] + + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + defines = [ + "APP_LOG_TAG = \"ANS_STANDARD\"", + "LOG_DOMAIN = 0xD001800", + ] +} + +ohos_shared_library("reminderagent") { + include_dirs = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common", + "//foundation/ace/napi/interfaces/kits/napi", + "//foundation/multimedia/image_standard/interfaces/kits/js/common/include/", + "../../include", + "//third_party/node/src", + "//third_party/libuv/include", + "//third_party/jsoncpp/include", + ] + + configs = [ ":native_module_config" ] + + sources = [ + "../common.cpp", + "../slot.cpp", + "native_module.cpp", + "publish.cpp", + "reminder_common.cpp", + ] + + deps = [ + "${frameworks_path}/ans/core:ans_core", + "${frameworks_path}/ans/native:ans_innerkits", + "${frameworks_path}/wantagent:wantagent_innerkits", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common:napi_common", + "//foundation/ace/napi:ace_napi", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/multimedia/image_standard/interfaces/innerkits:image", + "//third_party/jsoncpp:jsoncpp", + "//third_party/libuv:uv_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + relative_install_dir = "module" + subsystem_name = "notification" + part_name = "ans_standard" +} diff --git a/interfaces/kits/napi/ans/src/reminder/native_module.cpp b/interfaces/kits/napi/ans/src/reminder/native_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..386a92f3c550c05f4c0cb1f733aec382b9e21ed4 --- /dev/null +++ b/interfaces/kits/napi/ans/src/reminder/native_module.cpp @@ -0,0 +1,102 @@ +/* + * 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 "napi/native_api.h" +#include "napi/native_node_api.h" +#include "reminder/publish.h" +#include "slot.h" + +#include "reminder/native_module.h" + +namespace OHOS { +namespace ReminderAgentNapi { +EXTERN_C_START +napi_value ReminderAgentInit(napi_env env, napi_value exports) +{ + ANSR_LOGI("ReminderAgentInit start"); + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("cancelReminder", CancelReminder), + DECLARE_NAPI_FUNCTION("cancelAllReminders", CancelAllReminders), + DECLARE_NAPI_FUNCTION("getValidReminders", GetValidReminders), + DECLARE_NAPI_FUNCTION("publishReminder", PublishReminder), + DECLARE_NAPI_FUNCTION("addNotificationSlot", NotificationNapi::AddSlot), + DECLARE_NAPI_FUNCTION("removeNotificationSlot", NotificationNapi::RemoveSlot), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + return exports; +} + +napi_value ConstantInit(napi_env env, napi_value exports) +{ + ANSR_LOGI("ConstantInit start"); + napi_value objReminderType = nullptr; + napi_create_object(env, &objReminderType); + + napi_value prop = nullptr; + if (napi_create_int32(env, static_cast(ReminderRequest::ReminderType::TIMER), &prop) == napi_ok) { + napi_set_named_property(env, objReminderType, "REMINDER_TYPE_TIMER", prop); + } + if (napi_create_int32(env, static_cast(ReminderRequest::ReminderType::ALARM), &prop) == napi_ok) { + napi_set_named_property(env, objReminderType, "REMINDER_TYPE_ALARM", 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); + } + + napi_property_descriptor exportFuncs[] = { + DECLARE_NAPI_PROPERTY("ReminderType", objReminderType), + DECLARE_NAPI_PROPERTY("ActionButtonType", objButtonType), + }; + + napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs); + return exports; +}; +EXTERN_C_END + +/* + * Module define + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "reminderAgent", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +/* + * function for module exports + */ +static napi_value Init(napi_env env, napi_value exports) +{ + ReminderAgentInit(env, exports); + ConstantInit(env, exports); + return exports; +} + +/* + * Module register function + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace ReminderAgentNapi +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/ans/src/reminder/publish.cpp b/interfaces/kits/napi/ans/src/reminder/publish.cpp new file mode 100644 index 0000000000000000000000000000000000000000..699925f0c11b87733eb28ca3d8184e85afca0517 --- /dev/null +++ b/interfaces/kits/napi/ans/src/reminder/publish.cpp @@ -0,0 +1,561 @@ +/* + * 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 "common.h" +#include "reminder_request_alarm.h" +#include "reminder_request_timer.h" + +#include "reminder/publish.h" + +namespace OHOS { +namespace ReminderAgentNapi { +static const int32_t PUBLISH_PARAM_LEN = 2; +static const int32_t CANCEL_PARAM_LEN = 2; +static const int32_t CANCEL_ALL_PARAM_LEN = 1; +static const int32_t GET_VALID_PARAM_LEN = 1; + +struct AsyncCallbackInfo { + napi_env env = nullptr; + napi_async_work asyncWork = nullptr; + int32_t reminderId = -1; + std::shared_ptr reminder = nullptr; + NotificationNapi::CallbackPromiseInfo info; + napi_value result = nullptr; +}; + +struct Parameters { + int32_t reminderId = -1; + std::shared_ptr reminder = nullptr; + napi_ref callback = nullptr; +}; + +napi_value GetCallback(const napi_env &env, const napi_value &value, Parameters ¶ms) +{ + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, value, &valuetype)); + if (valuetype != napi_function) { + ANSR_LOGW("Wrong argument type. Function expected."); + return nullptr; + } + napi_create_reference(env, value, 1, ¶ms.callback); + return NotificationNapi::Common::NapiGetNull(env); +} + +AsyncCallbackInfo* SetAsynccallbackinfo(const napi_env &env, Parameters& params, napi_value& promise) +{ + AsyncCallbackInfo *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfo { + .env = env, .asyncWork = nullptr}; + if (!asynccallbackinfo) { + NotificationNapi::Common::JSParaError(env, params.callback); + return nullptr; + } + NotificationNapi::Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise); + return asynccallbackinfo; +} + +napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, Parameters ¶ms) +{ + size_t argc = PUBLISH_PARAM_LEN; + napi_value argv[PUBLISH_PARAM_LEN] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + if (argc < 1 || argc > PUBLISH_PARAM_LEN) { + ANSR_LOGW("Wrong number of arguments"); + return nullptr; + } + + // argv[0] : reminderRequest + if (ReminderCommon::GetReminderRequest(env, argv[0], params.reminder) == nullptr) { + ANSR_LOGW("[reminderAgent]CreateReminder returns nullptr"); + return nullptr; + } + + // argv[1]: callback + if (argc == PUBLISH_PARAM_LEN) { + if (GetCallback(env, argv[1], params) == nullptr) { + ANSR_LOGW("[reminderAgent]GetCallbak returns nullptr"); + return nullptr; + } + } + return NotificationNapi::Common::NapiGetNull(env); +} + +napi_value ParseCanCelParameter(const napi_env &env, const napi_callback_info &info, Parameters ¶ms) +{ + ANSR_LOGI("ParseCanCelParameter"); + size_t argc = CANCEL_PARAM_LEN; + napi_value argv[CANCEL_PARAM_LEN] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + if (argc < 1 || argc > CANCEL_PARAM_LEN) { + ANSR_LOGW("Wrong number of arguments"); + return nullptr; + } + + // 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."); + return nullptr; + } + if (reminderId < 0) { + ANSR_LOGW("Param id of cancels Reminder is illegal."); + return nullptr; + } + params.reminderId = reminderId; + + // argv[1]: callback + if (argc >= CANCEL_PARAM_LEN) { + if (GetCallback(env, argv[1], params) == nullptr) { + ANSR_LOGW("GetCallbak is nullptr"); + return nullptr; + } + } + return NotificationNapi::Common::NapiGetNull(env); +} + +napi_value ParseCanCelAllParameter(const napi_env &env, const napi_callback_info &info, Parameters ¶ms) +{ + ANSR_LOGI("ParseCanCelAllParameter"); + size_t argc = CANCEL_ALL_PARAM_LEN; + napi_value argv[CANCEL_ALL_PARAM_LEN] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + if (argc > CANCEL_ALL_PARAM_LEN) { + ANSR_LOGW("Wrong number of arguments"); + return nullptr; + } + + // argv[0]: callback + if (argc == CANCEL_ALL_PARAM_LEN) { + if (GetCallback(env, argv[0], params) == nullptr) { + ANSR_LOGW("getCallbak is nullptr"); + return nullptr; + } + } + return NotificationNapi::Common::NapiGetNull(env); +} + +napi_value ParseGetValidParameter(const napi_env &env, const napi_callback_info &info, Parameters ¶ms) +{ + size_t argc = GET_VALID_PARAM_LEN; + napi_value argv[GET_VALID_PARAM_LEN] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + if (argc < 0 || argc > GET_VALID_PARAM_LEN) { + ANSR_LOGW("Wrong number of arguments"); + return nullptr; + } + + // argv[0]: callback + if (argc == GET_VALID_PARAM_LEN) { + if (GetCallback(env, argv[0], params) == nullptr) { + ANSR_LOGW("getCallbak is nullptr"); + return nullptr; + } + } + return NotificationNapi::Common::NapiGetNull(env); +} + +napi_value CancelReminder(napi_env env, napi_callback_info info) +{ + ANSR_LOGI("Cancel reminder"); + + // param + Parameters params; + if (ParseCanCelParameter(env, info, params) == nullptr) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + + // promise + napi_value promise = nullptr; + AsyncCallbackInfo *asynccallbackinfo = SetAsynccallbackinfo(env, params, promise); + if (!asynccallbackinfo) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + asynccallbackinfo->reminderId = params.reminderId; + + // resource name + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "cancelReminder", NAPI_AUTO_LENGTH, &resourceName); + + // create and queue async work + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANSR_LOGI("Cancel napi_create_async_work start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + asynccallbackinfo->info.errorCode = ReminderHelper::CancelReminder(asynccallbackinfo->reminderId); + }, + [](napi_env env, napi_status status, void *data) { + ANSR_LOGI("Cancel napi_create_async_work complete start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + NotificationNapi::Common::ReturnCallbackPromise( + env, asynccallbackinfo->info, NotificationNapi::Common::NapiGetNull(env)); + if (asynccallbackinfo->info.callback != nullptr) { + napi_delete_reference(env, asynccallbackinfo->info.callback); + } + napi_delete_async_work(env, asynccallbackinfo->asyncWork); + if (asynccallbackinfo) { + delete asynccallbackinfo; + asynccallbackinfo = nullptr; + } + ANSR_LOGI("Cancel napi_create_async_work complete end"); + }, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork)); + + if (asynccallbackinfo->info.isCallback) { + return NotificationNapi::Common::NapiGetNull(env); + } else { + return promise; + } +} + +napi_value CancelAllReminders(napi_env env, napi_callback_info info) +{ + ANSR_LOGI("Cancel all reminder"); + + // param + Parameters params; + if (ParseCanCelAllParameter(env, info, params) == nullptr) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + + // promise + napi_value promise = nullptr; + AsyncCallbackInfo *asynccallbackinfo = SetAsynccallbackinfo(env, params, promise); + if (!asynccallbackinfo) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + + // resource name + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "cancelAllReminders", NAPI_AUTO_LENGTH, &resourceName); + + // create and queue async work + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANSR_LOGI("CancelAll napi_create_async_work start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + asynccallbackinfo->info.errorCode = ReminderHelper::CancelAllReminders(); + }, + [](napi_env env, napi_status status, void *data) { + ANSR_LOGD("CancelAll napi_create_async_work complete start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + NotificationNapi::Common::ReturnCallbackPromise( + env, asynccallbackinfo->info, NotificationNapi::Common::NapiGetNull(env)); + if (asynccallbackinfo->info.callback != nullptr) { + napi_delete_reference(env, asynccallbackinfo->info.callback); + } + napi_delete_async_work(env, asynccallbackinfo->asyncWork); + if (asynccallbackinfo) { + delete asynccallbackinfo; + asynccallbackinfo = nullptr; + } + ANSR_LOGD("CancelAll napi_create_async_work complete end"); + }, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork)); + + if (asynccallbackinfo->info.isCallback) { + return NotificationNapi::Common::NapiGetNull(env); + } else { + return promise; + } +} + +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); + 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"); + break; + } + default: { + break; + } + } +} + +void ParseActionButtons(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + auto actionButtonsMap = reminder.GetActionButtons(); + + // create array + napi_value array = nullptr; + napi_create_array(env, &array); + napi_set_named_property(env, result, ACTION_BUTTON, array); + 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); + + napi_value buttonInfo = nullptr; + napi_create_uint32(env, static_cast(it->second.type), &buttonInfo); + napi_set_named_property(env, actionButton, ACTION_BUTTON_TYPE, buttonInfo); + napi_create_string_utf8(env, (it->second.title).c_str(), NAPI_AUTO_LENGTH, &buttonInfo); + napi_set_named_property(env, actionButton, ACTION_BUTTON_TITLE, buttonInfo); + + // add obj to array + napi_set_element(env, array, index, actionButton); + index++; + } +} + +void ParseWantAgent(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + // create obj + napi_value wantAgentInfo = nullptr; + napi_create_object(env, &wantAgentInfo); + napi_set_named_property(env, result, WANT_AGENT, wantAgentInfo); + + napi_value info = nullptr; + napi_create_string_utf8(env, (reminder.GetWantAgentInfo()->pkgName).c_str(), NAPI_AUTO_LENGTH, &info); + napi_set_named_property(env, wantAgentInfo, WANT_AGENT_PKG, info); + napi_create_string_utf8(env, (reminder.GetWantAgentInfo()->abilityName).c_str(), NAPI_AUTO_LENGTH, &info); + napi_set_named_property(env, wantAgentInfo, WANT_AGENT_ABILITY, info); +} + +napi_value SetValidReminder(const napi_env &env, ReminderRequest &reminder, napi_value &result) +{ + ANSR_LOGI("enter"); + napi_value value = nullptr; + + napi_create_string_utf8(env, reminder.Dump().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "reminder", value); + + // type + ReminderRequest::ReminderType type = reminder.GetReminderType(); + napi_create_int32(env, static_cast(type), &value); + napi_set_named_property(env, result, REMINDER_TYPE, value); + + // reminder + ParseReminder(env, type, reminder, result); + + // title + napi_create_string_utf8(env, reminder.GetTitle().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, TITLE, value); + + // content + napi_create_string_utf8(env, reminder.GetContent().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, CONTENT, value); + + // expiredContent + napi_create_string_utf8(env, reminder.GetExpiredContent().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, EXPIRED_CONTENT, value); + + // notificationId + napi_create_int32(env, reminder.GetNotificationId(), &value); + napi_set_named_property(env, result, NOTIFICATION_ID, value); + + // slotType + NotificationNapi::SlotType jsSlotType; + NotificationNapi::Common::SlotTypeCToJS(reminder.GetSlotType(), jsSlotType); + napi_create_int32(env, static_cast(jsSlotType), &value); + napi_set_named_property(env, result, SLOT_TYPE, value); + + // wantAgent + ParseWantAgent(env, reminder, result); + + // actionButtons + ParseActionButtons(env, reminder, result); + + return NotificationNapi::Common::NapiGetBoolean(env, true); +} + +void GetValidRemindersInner(napi_env env, std::vector>& validReminders, napi_value& arr) +{ + int count = 0; + napi_create_array(env, &arr); + for (auto reminder : validReminders) { + if (reminder == nullptr) { + ANSR_LOGW("reminder is null"); + continue; + } + napi_value result = nullptr; + napi_create_object(env, &result); + if (!SetValidReminder(env, *reminder, result)) { + ANSR_LOGW("Set reminder object failed"); + continue; + } + napi_set_element(env, arr, count, result); + count++; + } + ANSR_LOGI("GetValid reminders count = %{public}d", count); +} + +napi_value GetValidReminders(napi_env env, napi_callback_info info) +{ + ANSR_LOGI("Get valid reminders"); + + // param + Parameters params; + if (ParseGetValidParameter(env, info, params) == nullptr) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + + // promise + napi_value promise = nullptr; + AsyncCallbackInfo *asynccallbackinfo = SetAsynccallbackinfo(env, params, promise); + if (!asynccallbackinfo) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + + // resource name + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "getValidReminders", NAPI_AUTO_LENGTH, &resourceName); + + // create and start async work + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANSR_LOGI("GetValid reminders napi_create_async_work start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + std::vector> validReminders; + asynccallbackinfo->info.errorCode = ReminderHelper::GetValidReminders(validReminders); + if (asynccallbackinfo->info.errorCode != ERR_OK) { + asynccallbackinfo->result = NotificationNapi::Common::NapiGetNull(env); + return; + } + napi_value arr = nullptr; + GetValidRemindersInner(env, validReminders, arr); + asynccallbackinfo->result = arr; + }, + [](napi_env env, napi_status status, void *data) { + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + NotificationNapi::Common::ReturnCallbackPromise( + env, asynccallbackinfo->info, asynccallbackinfo->result); + if (asynccallbackinfo->info.callback != nullptr) { + napi_delete_reference(env, asynccallbackinfo->info.callback); + } + napi_delete_async_work(env, asynccallbackinfo->asyncWork); + if (asynccallbackinfo) { + delete asynccallbackinfo; + asynccallbackinfo = nullptr; + } + }, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork)); + + if (asynccallbackinfo->info.isCallback) { + return NotificationNapi::Common::NapiGetNull(env); + } else { + return promise; + } +} + +napi_value PublishReminder(napi_env env, napi_callback_info info) +{ + ANSR_LOGI("PublishReminder"); + + // param + Parameters params; + if (ParseParameters(env, info, params) == nullptr) { + ANSR_LOGW("Parse params error"); + return NotificationNapi::Common::JSParaError(env, params.callback); + } + + // promise + napi_value promise = nullptr; + AsyncCallbackInfo *asynccallbackinfo = SetAsynccallbackinfo(env, params, promise); + if (!asynccallbackinfo) { + return NotificationNapi::Common::JSParaError(env, params.callback); + } + asynccallbackinfo->reminder = params.reminder; + + // resource name + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "publishReminder", NAPI_AUTO_LENGTH, &resourceName); + + // create and start async work + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANSR_LOGI("Publish napi_create_async_work start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + asynccallbackinfo->info.errorCode = ReminderHelper::PublishReminder(*(asynccallbackinfo->reminder)); + ANSR_LOGD("Return reminderId=%{public}d", asynccallbackinfo->reminder->GetReminderId()); + + // reminderId + napi_value napiReminderId = nullptr; + napi_create_int32(env, asynccallbackinfo->reminder->GetReminderId(), &napiReminderId); + asynccallbackinfo->result = napiReminderId; + }, + [](napi_env env, napi_status status, void *data) { + ANSR_LOGI("Publish napi_create_async_work complete start"); + AsyncCallbackInfo *asynccallbackinfo = (AsyncCallbackInfo *)data; + NotificationNapi::Common::ReturnCallbackPromise( + env, asynccallbackinfo->info, asynccallbackinfo->result); + if (asynccallbackinfo->info.callback != nullptr) { + napi_delete_reference(env, asynccallbackinfo->info.callback); + } + napi_delete_async_work(env, asynccallbackinfo->asyncWork); + if (asynccallbackinfo) { + delete asynccallbackinfo; + asynccallbackinfo = nullptr; + } + ANSR_LOGI("Publish napi_create_async_work complete end"); + }, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork)); + + if (asynccallbackinfo->info.isCallback) { + return NotificationNapi::Common::NapiGetNull(env); + } else { + return promise; + } +} +} +} \ No newline at end of file diff --git a/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp b/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b60e4780a765f08b785bee4d5b656cb8b607c80 --- /dev/null +++ b/interfaces/kits/napi/ans/src/reminder/reminder_common.cpp @@ -0,0 +1,377 @@ +/* + * 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 "common.h" +#include "reminder_request_alarm.h" +#include "reminder_request_timer.h" + +#include "reminder/reminder_common.h" + +namespace OHOS { +namespace ReminderAgentNapi { +using namespace OHOS::Notification; + +napi_value ReminderCommon::GetReminderRequest( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, value, &valuetype)); + if (valuetype != napi_object) { + ANSR_LOGE("Wrong argument type. Object expected."); + return nullptr; + } + + // gen reminder + if (GenReminder(env, value, reminder) == nullptr) { + return nullptr; + } + return NotificationNapi::Common::NapiGetNull(env); +} + +bool ReminderCommon::GenActionButtons( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + char str[NotificationNapi::STR_MAX_SIZE] = {0}; + napi_valuetype valuetype = napi_undefined; + napi_value actionButtons = nullptr; + if (!GetObject(env, value, ReminderAgentNapi::ACTION_BUTTON, actionButtons)) { + return true; + } + bool isArray = false; + napi_is_array(env, actionButtons, &isArray); + if (!isArray) { + ANSR_LOGE("Wrong argument type:%{public}s. array expected.", ACTION_BUTTON); + return false; + } + + uint32_t length = 0; + napi_get_array_length(env, actionButtons, &length); + for (size_t i = 0; i < length; i++) { + napi_value actionButton = nullptr; + 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); + 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) { + ANSR_LOGW("Wrong argument type:%{public}s. buttonType not support.", ACTION_BUTTON); + return false; + } + std::string title(str); + reminder->SetActionButton(title, static_cast(buttonType)); + ANSR_LOGD("button title=%{public}s, type=%{public}d", title.c_str(), buttonType); + } else { + ANSR_LOGW("Parse action button error."); + return false; + } + } + return true; +} + +void ReminderCommon::GenWantAgent( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + char str[NotificationNapi::STR_MAX_SIZE] = {0}; + napi_value wantAgent = nullptr; + if (GetObject(env, value, ReminderAgentNapi::WANT_AGENT, wantAgent)) { + auto wantAgentInfo = std::make_shared(); + if (GetStringUtf8(env, wantAgent, ReminderAgentNapi::WANT_AGENT_PKG, str, NotificationNapi::STR_MAX_SIZE)) { + wantAgentInfo->pkgName = str; + } + if (GetStringUtf8(env, wantAgent, + ReminderAgentNapi::WANT_AGENT_ABILITY, str, NotificationNapi::STR_MAX_SIZE)) { + wantAgentInfo->abilityName = str; + } + reminder->SetWantAgentInfo(wantAgentInfo); + } +} + +bool ReminderCommon::CreateReminder(const napi_env &env, const napi_value &value, + const int32_t &reminderType, std::shared_ptr& reminder) +{ + switch (ReminderRequest::ReminderType(reminderType)) { + case ReminderRequest::ReminderType::TIMER: + CreateReminderTimer(env, value, reminder); + break; + case ReminderRequest::ReminderType::ALARM: + CreateReminderAlarm(env, value, reminder); + break; + default: + ANSR_LOGW("Reminder type is not support."); + break; + } + if (reminder == nullptr) { + ANSR_LOGW("Instance of reminder error."); + return false; + } + return true; +} + +napi_value ReminderCommon::GenReminder( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + // reminderType + 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); + 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)) { + return nullptr; + } + char str[NotificationNapi::STR_MAX_SIZE] = {0}; + + // title + if (GetStringUtf8(env, value, ReminderAgentNapi::TITLE, str, NotificationNapi::STR_MAX_SIZE)) { + reminder->SetTitle(str); + } + + // content + if (GetStringUtf8(env, value, ReminderAgentNapi::CONTENT, str, NotificationNapi::STR_MAX_SIZE)) { + reminder->SetContent(str); + } + + // expiredContent + if (GetStringUtf8(env, value, ReminderAgentNapi::EXPIRED_CONTENT, str, NotificationNapi::STR_MAX_SIZE)) { + reminder->SetExpiredContent(str); + } + + // notificationId + if (GetInt32(env, value, ReminderAgentNapi::NOTIFICATION_ID, propertyVal)) { + reminder->SetNotificationId(propertyVal); + } + + // slotType + int32_t slotType = 0; + if (GetInt32(env, value, ReminderAgentNapi::SLOT_TYPE, slotType)) { + enum NotificationConstant::SlotType actureType = NotificationConstant::SlotType::OTHER; + if (!NotificationNapi::Common::SlotTypeJSToC(NotificationNapi::SlotType(slotType), actureType)) { + ANSR_LOGW("slot type not support."); + return nullptr; + } + reminder->SetSlotType(actureType); + } + + // wantAgent + GenWantAgent(env, value, reminder); + + // actionButtons + if (!GenActionButtons(env, value, reminder)) { + return nullptr; + } + return NotificationNapi::Common::NapiGetNull(env); +} + +bool ReminderCommon::GetStringUtf8(const napi_env &env, const napi_value &value, + const char* propertyName, char* propertyVal, const int32_t size) +{ + bool hasProperty = false; + napi_value result = nullptr; + napi_valuetype valuetype = napi_undefined; + size_t strLen = 0; + + NAPI_CALL(env, napi_has_named_property(env, value, propertyName, &hasProperty)); + if (hasProperty) { + 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); + return false; + } + NAPI_CALL(env, napi_get_value_string_utf8(env, result, propertyVal, size - 1, &strLen)); + } + return hasProperty; +} + +bool ReminderCommon::GetInt32(const napi_env &env, const napi_value &value, + const char* propertyName, int32_t& propertyVal) +{ + napi_value result = nullptr; + if (!GetPropertyValIfExist(env, value, propertyName, result)) { + return false; + } + napi_get_value_int32(env, result, &propertyVal); + return true; +} + +bool ReminderCommon::GetInt64(const napi_env &env, const napi_value &value, + const char* propertyName, int64_t& propertyVal) +{ + napi_value result = nullptr; + if (!GetPropertyValIfExist(env, value, propertyName, result)) { + return false; + } + napi_get_value_int64(env, result, &propertyVal); + return true; +} + +bool ReminderCommon::GetPropertyValIfExist(const napi_env &env, const napi_value &value, + const char* propertyName, napi_value& propertyVal) +{ + napi_valuetype valuetype = napi_undefined; + if (propertyName == nullptr) { + propertyVal = value; + } else { + bool hasProperty = false; + NAPI_CALL(env, napi_has_named_property(env, value, propertyName, &hasProperty)); + if (!hasProperty) { + return false; + } + napi_get_named_property(env, value, propertyName, &propertyVal); + } + NAPI_CALL(env, napi_typeof(env, propertyVal, &valuetype)); + if (valuetype != napi_number) { + if (propertyName == nullptr) { + ANSR_LOGW("Wrong argument type. number expected."); + } else { + ANSR_LOGW("Wrong argument type:%{public}s, number expected.", propertyName); + } + return false; + } + return true; +} + +bool ReminderCommon::GetObject(const napi_env &env, const napi_value &value, + const char* propertyName, napi_value& propertyVal) +{ + bool hasProperty = false; + napi_valuetype valuetype = napi_undefined; + + NAPI_CALL(env, napi_has_named_property(env, value, propertyName, &hasProperty)); + if (!hasProperty) { + return false; + } + 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); + return false; + } + return true; +} + +napi_value ReminderCommon::CreateReminderTimer( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + 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); + 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)); + return nullptr; + } + + reminder = std::make_shared(static_cast(propertyCountDownTime)); + return NotificationNapi::Common::NapiGetNull(env); +} + +napi_value ReminderCommon::CreateReminderAlarm( + const napi_env &env, const napi_value &value, std::shared_ptr& reminder) +{ + // hour + int32_t propertyHourVal = 0; + if (!GetInt32(env, value, ReminderAgentNapi::ALARM_HOUR, propertyHourVal)) { + ANSR_LOGE("Correct property %{public}s expected.", ReminderAgentNapi::ALARM_HOUR); + 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); + return nullptr; + } + if (propertyHourVal < 0 || propertyHourVal > 23) { + ANSR_LOGE("Property %{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); + return nullptr; + } + + // daysOfWeek + std::vector daysOfWeek; + ParseDaysOfWeek(env, value, daysOfWeek); + 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 result = nullptr; + if (!GetObject(env, value, ReminderAgentNapi::ALARM_DAYS_OF_WEEK, 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); + 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); + return nullptr; + } + napi_valuetype valuetype = napi_undefined; + for (size_t i = 0; i < length; i++) { + int32_t propertyDayVal = 10; + napi_value repeatDayVal = nullptr; + 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); + 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); + return nullptr; + } + daysOfWeek.push_back(static_cast(propertyDayVal)); + } + } + return NotificationNapi::Common::NapiGetNull(env); +} +} +} \ No newline at end of file diff --git a/notification.gni b/notification.gni index 61aa51bb018a459fec108f17f2f18460b97d781a..3039d020827e631a2fed299cc2c5ce895915e019 100644 --- a/notification.gni +++ b/notification.gni @@ -21,6 +21,8 @@ interfaces_path = "${ans_standard_path}/interfaces" core_path = "${frameworks_path}/ans/core" +native_path = "${frameworks_path}/ans/native" + test_path = "${ans_standard_path}/test" tools_path = "${ans_standard_path}/tools" diff --git a/ohos.build b/ohos.build index 747cde429e369f12c3689bc4e4b002f292cd031c..96a234c59a1f5ec2e75fcd35566017be0a5bd0e1 100644 --- a/ohos.build +++ b/ohos.build @@ -14,6 +14,7 @@ "//base/notification/ans_standard/services/ans/test/unittest:ans_unit_test", "//base/notification/ans_standard/services/test/moduletest:ans_module_test", "//base/notification/ans_standard/frameworks/ans/test/moduletest:moduletest", + "//base/notification/ans_standard/frameworks/ans/native/test/unittest:ans_reminder_unit_test", "//base/notification/ans_standard/frameworks/wantagent/test/:unittest", "//base/notification/ans_standard/test:systemtest" ] diff --git a/services/ans/BUILD.gn b/services/ans/BUILD.gn index 1f8e18f94a07171847fe6184bc7e51da0af0eab0..72614388f26fa28b0dd72142ccb1b8d5cd47b483 100644 --- a/services/ans/BUILD.gn +++ b/services/ans/BUILD.gn @@ -21,6 +21,7 @@ group("ans_targets") { config("public_ans_config") { include_dirs = [ "${services_path}/ans/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler/include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", @@ -44,6 +45,9 @@ ohos_shared_library("libans") { "src/notification_slot_filter.cpp", "src/notification_subscriber_manager.cpp", "src/permission_filter.cpp", + "src/reminder_data_manager.cpp", + "src/reminder_event_manager.cpp", + "src/reminder_timer_info.cpp", "src/system_event_observer.cpp", ] @@ -56,8 +60,10 @@ ohos_shared_library("libans") { "${core_path}:ans_core", "${frameworks_path}/ans/native:ans_innerkits", "${frameworks_path}/wantagent:wantagent_innerkits", + "//base/miscservices/time/services:time_service", "//foundation/aafwk/standard/services/abilitymgr:abilityms", "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr:distributedschedsvr", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", "//utils/native/base:utils", ] diff --git a/services/ans/include/advanced_notification_service.h b/services/ans/include/advanced_notification_service.h index 95214c02cb979749253cb10252c0cc128d12e48a..8479421503369e5abe2c9a49dd4803add27af2b2 100644 --- a/services/ans/include/advanced_notification_service.h +++ b/services/ans/include/advanced_notification_service.h @@ -108,12 +108,20 @@ public: ErrCode ShellDump(const std::string &dumpOption, std::vector &dumpInfo) override; ErrCode PublishContinuousTaskNotification(const sptr &request) override; ErrCode CancelContinuousTaskNotification(const std::string &label, int32_t notificationId) override; + ErrCode PublishReminder(sptr &reminder) override; + ErrCode CancelReminder(const int32_t reminderId) override; + ErrCode GetValidReminders(std::vector> &reminders) override; + ErrCode CancelAllReminders() override; // SystemEvent void OnBundleRemoved(const sptr &bundleOption); // Distributed KvStore void OnDistributedKvStoreDeathRecipient(); + ErrCode PrepareNotificationInfo( + const sptr &request, sptr &bundleOption); + ErrCode PublishPreparedNotification( + const sptr &request, const sptr &bundleOption); private: struct RecentInfo; diff --git a/services/ans/include/reminder_data_manager.h b/services/ans/include/reminder_data_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..8990973c2356a39ecfa16acbcb66513f84a2d57c --- /dev/null +++ b/services/ans/include/reminder_data_manager.h @@ -0,0 +1,321 @@ +/* + * 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_DATA_MANAGER_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_DATA_MANAGER_H + +#include +#include + +#include "advanced_notification_service.h" +#include "reminder_request.h" +#include "reminder_timer_info.h" + +namespace OHOS { +namespace Notification { +class ReminderDataManager final { +public: + ReminderDataManager() {}; + ~ReminderDataManager() {}; + + ReminderDataManager(ReminderDataManager &other) = delete; + ReminderDataManager& operator = (const ReminderDataManager &other) = delete; + + /** + * @brief Cancels all the reminders relative to the bundle option. + */ + void CancelAllReminders(const sptr &bundleOption); + + /** + * @brief Cancels the target reminder relative to the reminder id and bundle option. + * + * @param reminderId Indicates the reminder id. + * @param bundleOption Indicates the bundle option. + */ + void CancelReminder(const int32_t &reminderId, const sptr &bundleOption); + + /** + * @brief Close the target reminder which is showing on panel. + * This is manul operation by user: 1.Click close button of the reminder, 2.remove reminder notification. + * + * @param want Want information that transferred when the event trigger by user. + * @param cancelNotification Indicates whether need to cancel notification or not. + */ + void CloseReminder(const OHOS::EventFwk::Want &want, bool cancelNotification); + + /** + * Dump all the reminders information. + * + * @return reminders informations. + */ + std::string Dump() const; + + /** + * Obtains the single instance. + * + * @return Single instance of ReminderDataManager. + */ + static std::shared_ptr GetInstance(); + + /** + * Obtains all the valid reminders (which are not expired) relative to the bundle option. + * + * @param bundleOption Indicates the bundle option. + * @param[out] reminders return the valid reminders. + */ + void GetValidReminders( + const sptr bundleOption, std::vector> &reminders); + + /** + * Publishs a scheduled reminder. + * + * @param reminder Indicates the reminder. + * @param bundleOption Indicates bundle option the reminder belongs to. + */ + void PublishReminder(sptr &reminder, sptr &bundleOption); + + /** + * @brief Refresh all reminders when date/time or timeZone of device changed by user. + * + * @param type Indicates it is triggered by dateTime change or timeZone change. + */ + void RefreshRemindersDueToSysTimeChange(uint8_t type); + + /** + * @brief Indicates the single instance of ans that used to execute operations in service. + * + * @param Indicates the single instance of ans notification service. + */ + void SetService(AdvancedNotificationService *advancedNotificationService); + + /** + * @brief Show the reminder. + * + * @param isSysTimeChanged Indicates it is triggered as dateTime changed by user or not. + */ + void ShowReminder(bool isSysTimeChanged); + + static const uint8_t TIME_ZONE_CHANGE; + static const uint8_t DATE_TIME_CHANGE; + +private: + /** + * Cancels the notification relative to the reminder. + * + * @param reminder Indicates the reminder. + */ + void CancelNotification(sptr &reminder) const; + + /** + * Check whether the number limit of reminders if exceeded. + * + * @param bundleName Indicates the target bundle. + * @return true if number limit is exceeded. + */ + bool CheckReminderLimitExceededLocked(const std::string &bundleName) const; + + void CloseReminder(const int32_t &reminderId, bool cancelNotification); + + /** + * Create a information for timer, such as timer type, repeat policy, interval and want agent. + * + * @return pointer of ReminderTimerInfo. + */ + std::shared_ptr CreateTimerInfo() const; + + /** + * Find the reminder from reminderVector_ by reminder id. + * + * @param reminderId Indicates the reminder id. + * @return pointer of reminder request or nullptr. + */ + sptr FindReminderRequestLocked(const int32_t &reminderId); + + /** + * Find the reminder from {@link reminderVector_} and + * {@link notificationBundleOptionMap_} by reminder id and pkgName. + * + * @param reminderId Indicates the reminder id. + * @param pkgName Indicates the package name. + * @return pointer of reminder request or nullptr. + */ + sptr FindReminderRequestLocked(const int32_t &reminderId, const std::string &pkgName); + + /** + * Find bundle option from {@link notificationBundleOptionMap_} by reminder id. + * + * @param reminderId Indicates the reminder id. + * @return pointer of NotificationBundleOption or nullptr. + */ + sptr FindNotificationBundleOption(const int32_t &reminderId); + + /** + * Obtains the recent reminder which is not expired from reminder vector. + * + * The expired reminders will be removed from reminderVector_ and notificationBundleOptionMap_. + * + * @return pointer of reminder object. + */ + sptr GetRecentReminderLocked(); + + /** + * Obtains all the reminders of the target bundle name. + * + * @param bundleName Indicates the bundle name. + * @return all the reminders of the target bundle name. + */ + std::vector> GetSameBundleRemindersLocked(std::string &bundleName); + + void HandleImmediatelyShow(std::vector> &showImmediately, bool isSysTimeChanged); + + /** + * @brief Refresh the reminder due to date/time or timeZone change by user. + * + * @param type Indicates it is date/time change or timeZone change. + * @param reminder Indicates the target reminder. + * @return sptr Returns the target reminder if it is need to show immediately, otherwise nullptr. + */ + sptr HandleRefreshReminder(uint8_t &type, sptr &reminder); + + /** + * @brief Handles all the reminders that have the same notification id and belong to same application + * with the current reminder. Unset the state of "showing". + * + * @param reminder Indicates the current reminder. + */ + void HandleSameNotificationIdShowing(const sptr reminder); + + /** + * Judge the two reminders is belong to the same application or not. + * + * @param reminder Indicates the first reminder. + * @param otherPkgName Indicates the package name of second reminder. + * @param otherUserId Indicates the user id of second reminder. + * @return true if the two reminders belong to the same application. + */ + bool IsBelongToSameApp( + const sptr reminder, const std::string otherPkgName, const int otherUserId); + + /** + * @brief Refresh the all reminders due to date/time or timeZone change by user. + * + * @param type Indicates it is date/time change or timeZone change. + * @return reminders that need to show immediately. + */ + std::vector> RefreshRemindersLocked(uint8_t type); + + /** + * Removes the reminder. + * 1. removes the reminder from reminderVector_ and notificationBundleOptionMap_. + * 2. cancels the notification. + * + * @param reminderId Indicates the reminder id. + */ + void RemoveReminderLocked(const int32_t &reminderId); + + /** + * Resets timer status. + * 1. Sets timerId_ with 0. + * 2. Sets activeReminderId_ with -1. + */ + void ResetStates(); + + void ShowDesignatedReminderLocked(sptr &reminder, bool isSysTimeChanged); + + /** + * Starts the recent reminder timing. + */ + void StartRecentReminder(); + + /** + * Starts timing actually. + * + * @param reminderRequest Indicates the reminder. + */ + void StartTimerLocked(sptr &reminderRequest); + + /** + * Stops timing. + */ + void StopTimer(); + + /** + * Stops timing. + */ + void StopTimerLocked(); + + /** + * @brief Assign unique reminder id and save reminder in memory. + * + * @param reminder Indicates a reminder. + * @param bundleOption Indicates bundle option relative to the reminder. + */ + void UpdateAndSaveReminderLocked( + const sptr &reminder, const sptr &bundleOption); + + static bool cmp(sptr &reminderRequest, sptr &other); + + /** + * Single instance. + */ + static std::shared_ptr REMINDER_DATA_MANAGER; + + /** + * Used for multi-thread syncronise. + */ + static std::mutex MUTEX; + + /** + * Max number of reminders limit for the whole system. + */ + static const int16_t MAX_NUM_REMINDER_LIMIT_SYSTEM; + + /** + * Max number of reminders limit for one application. + */ + 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_; + + /** + * 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. + */ + uint64_t timerId_ {0}; + + /** + * Indicates the active reminder that timing is taking effect. + */ + int32_t activeReminderId_ {-1}; + + /** + * Indicates the total count of reminders in system. + */ + int16_t totalCount_ {0}; + AdvancedNotificationService *advancedNotificationService_; +}; +} // 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 new file mode 100644 index 0000000000000000000000000000000000000000..25a20792aa8ed0dd12ffa4ed1a94c681b77cef66 --- /dev/null +++ b/services/ans/include/reminder_event_manager.h @@ -0,0 +1,48 @@ +/* + * 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_EVENT_MANAGER_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_EVENT_MANAGER_H + +#include "common_event_subscriber.h" +#include "reminder_data_manager.h" + +#include + +namespace OHOS { +namespace Notification { +class ReminderEventManager { +public: + ReminderEventManager(std::shared_ptr &reminderDataManager); + virtual ~ReminderEventManager() {}; + ReminderEventManager(ReminderEventManager &other) = delete; + ReminderEventManager& operator = (const ReminderEventManager &other) = delete; + +private: + void init(std::shared_ptr &reminderDataManager) const; + +class ReminderEventSubscriber : public EventFwk::CommonEventSubscriber { +public: + ReminderEventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo, + std::shared_ptr &reminderDataManager); + virtual void OnReceiveEvent(const EventFwk::CommonEventData &data); + +private: + std::shared_ptr reminderDataManager_; +}; +}; +} // namespace OHOS +} // namespace Notification +#endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_EVENT_MANAGER_H diff --git a/services/ans/include/reminder_timer_info.h b/services/ans/include/reminder_timer_info.h new file mode 100644 index 0000000000000000000000000000000000000000..0bc1e891e0c8fde42d73b3881c1f73e14738fd29 --- /dev/null +++ b/services/ans/include/reminder_timer_info.h @@ -0,0 +1,67 @@ +/* + * 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_TIMER_INFO_H +#define BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_TIMER_INFO_H + +#include "advanced_notification_service.h" +#include "itimer_info.h" +#include "notification_request.h" +#include "reminder_request.h" + +namespace OHOS { +namespace Notification { +class ReminderTimerInfo : public MiscServices::ITimerInfo { +public: + ReminderTimerInfo() {}; + virtual ~ReminderTimerInfo() {}; + + ReminderTimerInfo(ReminderTimerInfo &other) = delete; + ReminderTimerInfo& operator = (const ReminderTimerInfo &other) = delete; + + /** + * When timing is up, this function will execute as call back. + */ + void OnTrigger() override; + + /** + * Indicates the timing type. + */ + void SetType(const int &type) override; + + /** + * Indicates the repeat policy. + */ + void SetRepeat(bool repeat) override; + + /** + * Indicates the interval time for repeat timing. + */ + void SetInterval(const uint64_t &interval) override; + + /** + * Indicates the want agent information. + */ + void SetWantAgent(std::shared_ptr wantAgent) override; + + /** + * Publish common event. + */ + bool PublishCommonEvent(const std::string &action) const; +}; +} // namespace OHOS +} // namespace Notification + +#endif // BASE_NOTIFICATION_ANS_STANDARD_FRAMEWORKS_ANS_CORE_INCLUDE_REMINDER_TIMER_INFO_H diff --git a/services/ans/src/advanced_notification_service.cpp b/services/ans/src/advanced_notification_service.cpp index c0995fcd110b3b73a682a7bf6b466c5d46ece0a8..1a1652fd409a4245635438a9cec799b4bc3915fa 100644 --- a/services/ans/src/advanced_notification_service.cpp +++ b/services/ans/src/advanced_notification_service.cpp @@ -31,6 +31,7 @@ #include "notification_slot_filter.h" #include "notification_subscriber_manager.h" #include "permission_filter.h" +#include "reminder_data_manager.h" namespace OHOS { namespace Notification { @@ -227,29 +228,34 @@ sptr AdvancedNotificationService::GenerateValidBundleO return validBundleOption; } -ErrCode AdvancedNotificationService::Publish(const std::string &label, const sptr &request) +ErrCode AdvancedNotificationService::PrepareNotificationInfo( + const sptr &request, sptr &bundleOption) { - ANS_LOGD("%{public}s", __FUNCTION__); - if ((request->GetSlotType() == NotificationConstant::SlotType::CUSTOM) && !IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } - ErrCode result = PrepereNotificationRequest(request); if (result != ERR_OK) { return result; } - - sptr bundleOption = GenerateBundleOption(); + bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { return ERR_ANS_INVALID_BUNDLE; } + ANS_LOGI( + "bundleName=%{public}s, uid=%{public}d", (bundleOption->GetBundleName()).c_str(), bundleOption->GetUid()); + return ERR_OK; +} - std::shared_ptr record = std::make_shared(); +ErrCode AdvancedNotificationService::PublishPreparedNotification( + const sptr &request, const sptr &bundleOption) +{ + ANS_LOGI("PublishPreparedNotification"); + auto record = std::make_shared(); record->request = request; record->notification = new Notification(request); record->bundleOption = bundleOption; - + ErrCode result = ERR_OK; handler_->PostSyncTask(std::bind([&]() { result = AssignValidNotificationSlot(record); if (result != ERR_OK) { @@ -276,15 +282,24 @@ ErrCode AdvancedNotificationService::Publish(const std::string &label, const spt } UpdateInNotificationList(record); } - UpdateRecentNotification(record->notification, false, 0); sptr sortingMap = GenerateSortingMap(); NotificationSubscriberManager::GetInstance()->NotifyConsumed(record->notification, sortingMap); })); - return result; } +ErrCode AdvancedNotificationService::Publish(const std::string &label, const sptr &request) +{ + ANS_LOGD("%{public}s", __FUNCTION__); + sptr bundleOption; + ErrCode result = PrepareNotificationInfo(request, bundleOption); + if (result != ERR_OK) { + return result; + } + return PublishPreparedNotification(request, bundleOption); +} + bool AdvancedNotificationService::IsNotificationExists(const std::string &key) { bool isExists = false; @@ -1376,6 +1391,59 @@ ErrCode AdvancedNotificationService::CancelContinuousTaskNotification(const std: return result; } +ErrCode AdvancedNotificationService::PublishReminder(sptr &reminder) +{ + ANSR_LOGI("Publish reminder"); + ReminderDataManager::GetInstance()->SetService(this); + sptr notificationRequest = reminder->GetNotificationRequest(); + sptr bundleOption = nullptr; + ErrCode result = PrepareNotificationInfo(notificationRequest, bundleOption); + if (result != ERR_OK) { + ANSR_LOGW("PrepareNotificationInfo fail"); + return result; + } + ReminderDataManager::GetInstance()->PublishReminder(reminder, bundleOption); + return ERR_OK; +} + +ErrCode AdvancedNotificationService::CancelReminder(const int32_t reminderId) +{ + ANSR_LOGI("Cancel Reminder"); + ReminderDataManager::GetInstance()->SetService(this); + sptr bundleOption = GenerateBundleOption(); + if (bundleOption == nullptr) { + return ERR_ANS_INVALID_BUNDLE; + } + ReminderDataManager::GetInstance()->CancelReminder(reminderId, bundleOption); + return ERR_OK; +} + +ErrCode AdvancedNotificationService::CancelAllReminders() +{ + ANSR_LOGI("Cancel all reminders"); + ReminderDataManager::GetInstance()->SetService(this); + sptr bundleOption = GenerateBundleOption(); + if (bundleOption == nullptr) { + return ERR_ANS_INVALID_BUNDLE; + } + ReminderDataManager::GetInstance()->CancelAllReminders(bundleOption); + return ERR_OK; +} + +ErrCode AdvancedNotificationService::GetValidReminders(std::vector> &reminders) +{ + ANSR_LOGI("GetValidReminders"); + ReminderDataManager::GetInstance()->SetService(this); + reminders.clear(); + sptr bundleOption = GenerateBundleOption(); + if (bundleOption == nullptr) { + return ERR_ANS_INVALID_BUNDLE; + } + ReminderDataManager::GetInstance()->GetValidReminders(bundleOption, reminders); + ANSR_LOGD("Valid reminders size=%{public}zu", reminders.size()); + return ERR_OK; +} + ErrCode AdvancedNotificationService::ActiveNotificationDump(std::vector &dumpInfo) { ANS_LOGD("%{public}s", __FUNCTION__); diff --git a/services/ans/src/reminder_data_manager.cpp b/services/ans/src/reminder_data_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c89e937b5954b89b3fb6f9a703c3caf24668f728 --- /dev/null +++ b/services/ans/src/reminder_data_manager.cpp @@ -0,0 +1,601 @@ +/* + * 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 "common_event_support.h" +#include "reminder_event_manager.h" +#include "time_service_client.h" +#include "singleton.h" + +#include "reminder_data_manager.h" + +namespace OHOS { +namespace Notification { +const int16_t ReminderDataManager::MAX_NUM_REMINDER_LIMIT_SYSTEM = 2000; +const int16_t ReminderDataManager::MAX_NUM_REMINDER_LIMIT_APP = 30; +const uint16_t ReminderDataManager::SAME_TIME_DISTINGUISH_MILLISECONDS = 1000; +const uint8_t ReminderDataManager::TIME_ZONE_CHANGE = 0; +const uint8_t ReminderDataManager::DATE_TIME_CHANGE = 1; +std::shared_ptr ReminderDataManager::REMINDER_DATA_MANAGER = nullptr; +std::mutex ReminderDataManager::MUTEX; + +void ReminderDataManager::PublishReminder(sptr &reminder, + sptr &bundleOption) +{ + if (CheckReminderLimitExceededLocked(bundleOption->GetBundleName())) { + return; + } + UpdateAndSaveReminderLocked(reminder, bundleOption); + StartRecentReminder(); +} + +void ReminderDataManager::CancelReminder( + const int32_t &reminderId, const sptr &bundleOption) +{ + sptr reminder = FindReminderRequestLocked(reminderId, bundleOption->GetBundleName()); + if (reminder == nullptr) { + ANSR_LOGW("Cancel reminder, not find the reminder"); + return; + } + if (activeReminderId_ != -1 && activeReminderId_ == reminderId) { + ANSR_LOGD("Cancel active reminder, id=%{public}d", activeReminderId_); + StopTimerLocked(); + } + int32_t id = reminderId; + RemoveReminderLocked(id); + CancelNotification(reminder); + StartRecentReminder(); +} + +void ReminderDataManager::CancelNotification(sptr &reminder) const +{ + if (!(reminder->IsShowing())) { + ANSR_LOGD("No need to cancel notification"); + return; + } + sptr notification = reminder->GetNotificationRequest(); + if (notification == nullptr) { + ANSR_LOGW("Cancel notification fail"); + return; + } + ANSR_LOGD("Cancel notification"); + if (advancedNotificationService_ == nullptr) { + ANSR_LOGE("Cancel notification fail"); + return; + } + advancedNotificationService_->Cancel(notification->GetNotificationId(), ReminderRequest::NOTIFICATION_LABEL); +} + +bool ReminderDataManager::CheckReminderLimitExceededLocked(const std::string &bundleName) const +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + if (totalCount_ >= ReminderDataManager::MAX_NUM_REMINDER_LIMIT_SYSTEM) { + ANSR_LOGW("The number of validate reminders exceeds the system upper limit:%{public}d, \ + and new reminder can not be published", MAX_NUM_REMINDER_LIMIT_SYSTEM); + return true; + } + int8_t count = 0; + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if ((*it)->IsExpired()) { + continue; + } + auto mit = notificationBundleOptionMap_.find((*it)->GetReminderId()); + if (mit == notificationBundleOptionMap_.end()) { + ANSR_LOGE("Error occur when get bundle option, reminderId=%{public}d", (*it)->GetReminderId()); + } else { + if (mit->second->GetBundleName() == bundleName) { + count++; + } + } + } + if (count >= ReminderDataManager::MAX_NUM_REMINDER_LIMIT_APP) { + ANSR_LOGW("The number of validate reminders exceeds the application upper limit:%{public}d, and new \ + reminder can not be published", MAX_NUM_REMINDER_LIMIT_APP); + return true; + } + return false; +} + +void ReminderDataManager::CancelAllReminders(const sptr &bundleOption) +{ + MUTEX.lock(); + auto it = notificationBundleOptionMap_.find(activeReminderId_); + if (it == notificationBundleOptionMap_.end()) { + ANSR_LOGD("Get bundle option error, reminderId=%{public}d", activeReminderId_); + } else { + if (it->second->GetBundleName() == bundleOption->GetBundleName()) { + StopTimer(); + } + } + for (auto vit = reminderVector_.begin(); vit != reminderVector_.end();) { + int32_t reminderId = (*vit)->GetReminderId(); + auto mit = notificationBundleOptionMap_.find(reminderId); + if (mit == notificationBundleOptionMap_.end()) { + ANSR_LOGE("Get bundle option occur error, reminderId=%{public}d", reminderId); + } else { + if (mit->second->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; + } + MUTEX.unlock(); + StartRecentReminder(); +} + +void ReminderDataManager::GetValidReminders( + const sptr bundleOption, std::vector> &reminders) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if ((*it)->IsExpired()) { + continue; + } + 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); + } else { + if (mit->second->GetBundleName() == bundleOption->GetBundleName()) { + reminders.push_back(*it); + } + } + } +} + +std::shared_ptr ReminderDataManager::CreateTimerInfo() 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); + return sharedTimerInfo; +} + +sptr ReminderDataManager::FindReminderRequestLocked(const int32_t &reminderId) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if (reminderId == (*it)->GetReminderId()) { + return *it; + } + } + ANSR_LOGD("Not find the reminder"); + return nullptr; +} + +sptr ReminderDataManager::FindReminderRequestLocked( + const int32_t &reminderId, const std::string &pkgName) +{ + sptr reminder = FindReminderRequestLocked(reminderId); + std::lock_guard lock(ReminderDataManager::MUTEX); + if (reminder == nullptr) { + return nullptr; + } + auto bundleOption = FindNotificationBundleOption(reminderId); + if (bundleOption == nullptr) { + ANSR_LOGW("Not find the reminder due to bundle info is null"); + return nullptr; + } + if (bundleOption -> GetBundleName() != pkgName) { + ANSR_LOGW("Not find the reminder due to package name not match"); + return nullptr; + } + return reminder; +} + +sptr ReminderDataManager::FindNotificationBundleOption(const int32_t &reminderId) +{ + auto it = notificationBundleOptionMap_.find(reminderId); + if (it == notificationBundleOptionMap_.end()) { + return nullptr; + } else { + return it->second; + } +} + +bool ReminderDataManager::cmp(sptr &reminderRequest, sptr &other) +{ + return reminderRequest->GetTriggerTimeInMilli() < other->GetTriggerTimeInMilli(); +} + +void ReminderDataManager::CloseReminder(const OHOS::EventFwk::Want &want, bool cancelNotification) +{ + int32_t reminderId = static_cast(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) { + ANSR_LOGD("Stop active reminder due to CloseReminder"); + StopTimerLocked(); + } + reminder->OnClose(true); + if (cancelNotification) { + CancelNotification(reminder); + } + StartRecentReminder(); +} + +std::shared_ptr ReminderDataManager::GetInstance() +{ + if (REMINDER_DATA_MANAGER == nullptr) { + REMINDER_DATA_MANAGER = std::make_shared(); + ReminderEventManager reminderEventManager(REMINDER_DATA_MANAGER); + } + return REMINDER_DATA_MANAGER; +} + +void ReminderDataManager::RefreshRemindersDueToSysTimeChange(uint8_t type) +{ + std::string typeInfo = type == TIME_ZONE_CHANGE ? "timeZone" : "dateTime"; + 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(); + } + std::vector> showImmediately = RefreshRemindersLocked(type); + if (!showImmediately.empty()) { + ANSR_LOGD("Refresh all reminders, show expired reminders immediately"); + HandleImmediatelyShow(showImmediately, true); + } + StartRecentReminder(); +} + +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); + auto ret = notificationBundleOptionMap_.insert( + std::pair>(reminderId, bundleOption)); + if (!ret.second) { + ANSR_LOGE("Containers add to map error"); + return; + } + reminderVector_.push_back(reminder); + totalCount_++; +} + +void ReminderDataManager::SetService(AdvancedNotificationService *advancedNotificationService) +{ + advancedNotificationService_ = advancedNotificationService; +} + +void ReminderDataManager::ShowReminder(bool isSysTimeChanged) +{ + ANSR_LOGD("ShowReminder"); + if (activeReminderId_ == -1) { + ANSR_LOGE("Active reminder not exist"); + return; + } + sptr reminder = FindReminderRequestLocked(activeReminderId_); + ShowDesignatedReminderLocked(reminder, isSysTimeChanged); + ResetStates(); + StartRecentReminder(); +} + +void ReminderDataManager::ShowDesignatedReminderLocked(sptr &reminder, bool isSysTimeChanged) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + uint64_t triggerTime = reminder->GetTriggerTimeInMilli(); + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if ((*it)->IsExpired()) { + continue; + } + if ((*it)->GetTriggerTimeInMilli() - triggerTime > ReminderDataManager::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 (advancedNotificationService_ == nullptr) { + ANSR_LOGE("ShowReminder fail"); + (*it)->OnShow(isSysTimeChanged, false); + } 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)); + } + } +} + +void ReminderDataManager::StartRecentReminder() +{ + sptr reminder = GetRecentReminderLocked(); + if (reminder == nullptr) { + ANSR_LOGI("No reminder need to start"); + return; + } + + 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; + } + } + if (toStart) { + ANSR_LOGI("Start recent reminder"); + StartTimerLocked(reminder); + } +} + +void ReminderDataManager::StopTimer() +{ + if (timerId_ == 0) { + ANSR_LOGD("Timer is not running"); + return; + } + ANSR_LOGD("Stop timer id=%{public}llu", (unsigned long long)timerId_); + sptr timer = MiscServices::TimeServiceClient::GetInstance(); + timer->StopTimer(timerId_); + ResetStates(); +} + +void ReminderDataManager::StopTimerLocked() +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + StopTimer(); +} + +std::string ReminderDataManager::Dump() const +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + std::map>> bundleNameMap; + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + if ((*it)->IsExpired()) { + continue; + } + int32_t reminderId = (*it)->GetReminderId(); + auto mit = notificationBundleOptionMap_.find(reminderId); + if (mit == notificationBundleOptionMap_.end()) { + ANSR_LOGE("Dump get notificationBundleOption(reminderId=%{public}d) fail", reminderId); + continue; + } + std::string bundleName = mit->second->GetBundleName(); + auto val = bundleNameMap.find(bundleName); + if (val == bundleNameMap.end()) { + std::vector> reminders; + reminders.push_back(*it); + bundleNameMap.insert(std::pair>>(bundleName, reminders)); + } else { + val->second.push_back(*it); + } + } + + std::string allReminders = ""; + for (auto it = bundleNameMap.begin(); it != bundleNameMap.end(); ++it) { + std::string bundleName = it->first; + std::vector> reminders = it->second; + sort(reminders.begin(), reminders.end(), cmp); + std::string oneBundleReminders = bundleName + ":{\n"; + oneBundleReminders += " totalCount:" + std::to_string(reminders.size()) + ",\n"; + oneBundleReminders += " reminders:{\n"; + for (auto vit = reminders.begin(); vit != reminders.end(); ++vit) { + oneBundleReminders += " [\n"; + std::string reminderInfo = (*vit)->Dump(); + oneBundleReminders += " " + reminderInfo + "\n"; + oneBundleReminders += " ],\n"; + } + oneBundleReminders += " },\n"; + oneBundleReminders += "},\n"; + allReminders += oneBundleReminders; + } + + return "ReminderDataManager{ totalCount:" + std::to_string(totalCount_) + ",\n" + + "timerId:" + std::to_string(timerId_) + ",\n" + + "activeReminderId:" + std::to_string(activeReminderId_) + ",\n" + + allReminders + "}"; +} + +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++; + continue; + } + int32_t reminderId = (*reminder)->GetReminderId(); + ANSR_LOGD("Containers(vector) remove. reminderId=%{public}d", reminderId); + auto it = notificationBundleOptionMap_.find((*reminder)->GetReminderId()); + if (it == notificationBundleOptionMap_.end()) { + ANSR_LOGE("Remove notificationBundleOption(reminderId=%{public}d) fail", + (*reminder)->GetReminderId()); + } else { + ANSR_LOGD("Containers(map) remove. reminderId=%{public}d", reminderId); + notificationBundleOptionMap_.erase(it); + } + reminder = reminderVector_.erase(reminder); + totalCount_--; + } + return nullptr; +} + +std::vector> ReminderDataManager::GetSameBundleRemindersLocked(std::string &bundleName) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + std::vector> reminders; + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + sptr bundleOption = FindNotificationBundleOption((*it)->GetReminderId()); + if (bundleOption == nullptr) { + ANSR_LOGW("GetSameBundleRemindersLocked get notificationBundleOption(reminderId=%{public}d) fail", + (*it)->GetReminderId()); + continue; + } + if (bundleName == bundleOption->GetBundleName()) { + reminders.push_back((*it)); + } + } + return reminders; +} + +void ReminderDataManager::HandleImmediatelyShow( + std::vector> &showImmediately, bool isSysTimeChanged) +{ + for (auto it = showImmediately.begin(); it != showImmediately.end(); ++it) { + ShowDesignatedReminderLocked((*it), isSysTimeChanged); + } +} + +sptr ReminderDataManager::HandleRefreshReminder(uint8_t &type, sptr &reminder) +{ + bool needShowImmediately = false; + if (type == TIME_ZONE_CHANGE) { + needShowImmediately = reminder->OnTimeZoneChange(); + } + if (type == DATE_TIME_CHANGE) { + needShowImmediately = reminder->OnDateTimeChange(); + } + if (!needShowImmediately) { + return nullptr; + } else { + return reminder; + } +} + +void ReminderDataManager::HandleSameNotificationIdShowing(const sptr reminder) +{ + // not add ReminderDataManager::MUTEX, as ShowDesignatedReminderLocked has locked + int32_t notificationId = reminder->GetNotificationId(); + ANSR_LOGD("HandleSameNotificationIdShowing notificationId=%{public}d", notificationId); + int32_t curReminderId = reminder->GetReminderId(); + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + int32_t tmpId = (*it)->GetReminderId(); + if (tmpId == curReminderId) { + continue; + } + if (!(*it)->IsShowing()) { + continue; + } + sptr bundleOption = FindNotificationBundleOption(tmpId); + if (bundleOption == nullptr) { + ANSR_LOGW("Get notificationBundleOption(reminderId=%{public}d) fail", tmpId); + continue; + } + if (notificationId == (*it)->GetNotificationId() && + IsBelongToSameApp(reminder, bundleOption->GetBundleName(), 0)) { + (*it)->OnSameNotificationIdCovered(); + } + } +} + +bool ReminderDataManager::IsBelongToSameApp( + const sptr reminder, const std::string otherPkgName, const int otherUserId) +{ + ANSR_LOGD("otherUserId=%{public}d, (currently, userId not support)", otherUserId); + int32_t reminderId = reminder->GetReminderId(); + sptr bundleOption = FindNotificationBundleOption(reminderId); + if (bundleOption == nullptr) { + ANSR_LOGW("IsBelongToSameApp get notificationBundleOption(reminderId=%{public}d) fail", reminderId); + return false; + } + if (bundleOption->GetBundleName() == otherPkgName) { + return true; + } + return false; +} + +std::vector> ReminderDataManager::RefreshRemindersLocked(uint8_t type) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + std::vector> showImmediately; + for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) { + sptr reminder = HandleRefreshReminder(type, (*it)); + if (reminder != nullptr) { + showImmediately.push_back(reminder); + } + } + return showImmediately; +} + +void ReminderDataManager::RemoveReminderLocked(const int32_t &reminderId) +{ + std::lock_guard lock(ReminderDataManager::MUTEX); + for (auto it = reminderVector_.begin(); it != reminderVector_.end();) { + if (reminderId == (*it)->GetReminderId()) { + 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; + } + } + auto it = notificationBundleOptionMap_.find(reminderId); + if (it == notificationBundleOptionMap_.end()) { + ANSR_LOGE("Remove notificationBundleOption(reminderId=%{public}d) fail", reminderId); + } else { + ANSR_LOGD("Containers(map) remove: reminderId=%{public}d", reminderId); + notificationBundleOptionMap_.erase(it); + } +} + +void ReminderDataManager::ResetStates() +{ + ANSR_LOGD("ResetStates"); + timerId_ = 0; + activeReminderId_ = -1; +} + +void ReminderDataManager::StartTimerLocked(sptr &reminderRequest) +{ + ANSR_LOGD("Start timer: millSeconds=%{public}llu", (unsigned long long)(reminderRequest->GetTriggerTimeInMilli())); + std::lock_guard lock(ReminderDataManager::MUTEX); + sptr timer = MiscServices::TimeServiceClient::GetInstance(); + timerId_ = timer->CreateTimer(REMINDER_DATA_MANAGER->CreateTimerInfo()); + timer->StartTimer(timerId_, reminderRequest->GetTriggerTimeInMilli()); + activeReminderId_ = reminderRequest->GetReminderId(); +} +} +} \ No newline at end of file diff --git a/services/ans/src/reminder_event_manager.cpp b/services/ans/src/reminder_event_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..117c8312cec2c0003bc02c3f809ab51bab60ced6 --- /dev/null +++ b/services/ans/src/reminder_event_manager.cpp @@ -0,0 +1,101 @@ +/* + * 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 "common_event_manager.h" +#include "common_event_support.h" +#include "bundle_constants.h" + +#include "reminder_event_manager.h" + +using namespace OHOS::EventFwk; +namespace OHOS { +namespace Notification { +ReminderEventManager::ReminderEventManager(std::shared_ptr &reminderDataManager) +{ + init(reminderDataManager); +} + +void ReminderEventManager::init(std::shared_ptr &reminderDataManager) const +{ + MatchingSkills matchingSkills; + matchingSkills.AddEvent(ReminderRequest::REMINDER_EVENT_ALARM_ALERT); + matchingSkills.AddEvent(ReminderRequest::REMINDER_EVENT_CLOSE_ALERT); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_RESTARTED); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_TIME_CHANGED); + CommonEventSubscribeInfo subscriberInfo(matchingSkills); + auto subscriber = std::make_shared(subscriberInfo, reminderDataManager); + if (CommonEventManager::SubscribeCommonEvent(subscriber)) { + ANSR_LOGD("SubscribeCommonEvent ok"); + } else { + ANSR_LOGD("SubscribeCommonEvent fail"); + } +} + +ReminderEventManager::ReminderEventSubscriber::ReminderEventSubscriber( + const CommonEventSubscribeInfo &subscriberInfo, + std::shared_ptr &reminderDataManager) : CommonEventSubscriber(subscriberInfo) +{ + reminderDataManager_ = reminderDataManager; +} + +void ReminderEventManager::ReminderEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data) +{ + Want want = data.GetWant(); + std::string action = want.GetAction(); + ANSR_LOGD("Recieved common event:%{public}s", action.c_str()); + if (action == ReminderRequest::REMINDER_EVENT_ALARM_ALERT) { + reminderDataManager_->ShowReminder(false); + return; + } + if (action == ReminderRequest::REMINDER_EVENT_CLOSE_ALERT) { + reminderDataManager_->CloseReminder(want, true); + 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); + return; + } + if (action == CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED) { + // todo + return; + } + if (action == CommonEventSupport::COMMON_EVENT_PACKAGE_RESTARTED) { + // todo + return; + } + if (action == CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED) { + reminderDataManager_->RefreshRemindersDueToSysTimeChange(ReminderDataManager::TIME_ZONE_CHANGE); + return; + } + if (action == CommonEventSupport::COMMON_EVENT_TIME_CHANGED) { + reminderDataManager_->RefreshRemindersDueToSysTimeChange(ReminderDataManager::DATE_TIME_CHANGE); + return; + } +} +} // namespace OHOS +} // namespace Notification \ No newline at end of file diff --git a/services/ans/src/reminder_timer_info.cpp b/services/ans/src/reminder_timer_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c7c39c873573b5cf5bb7eb3e060afa287ec62ce --- /dev/null +++ b/services/ans/src/reminder_timer_info.cpp @@ -0,0 +1,62 @@ +/* + * 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 "common_event_manager.h" +#include "reminder_request.h" + +#include "reminder_timer_info.h" + +using namespace OHOS::EventFwk; +namespace OHOS { +namespace Notification { +void ReminderTimerInfo::SetType(const int &_type) +{ + type = _type; +} + +void ReminderTimerInfo::SetRepeat(bool _repeat) +{ + repeat = _repeat; +} + +void ReminderTimerInfo::SetInterval(const uint64_t &_interval) +{ + interval = _interval; +} + +void ReminderTimerInfo::SetWantAgent(std::shared_ptr _wantAgent) +{ + wantAgent = _wantAgent; +} + +void ReminderTimerInfo::OnTrigger() +{ + ANSR_LOGI("ReminderTimer is triggerred"); + PublishCommonEvent(ReminderRequest::REMINDER_EVENT_ALARM_ALERT); +} + +bool ReminderTimerInfo::PublishCommonEvent(const std::string &action) const +{ + Want want; + want.SetAction(action); + CommonEventData data; + data.SetWant(want); + CommonEventPublishInfo publishInfo; + publishInfo.SetOrdered(false); + return CommonEventManager::PublishCommonEvent(data, publishInfo); +} +} +} \ No newline at end of file diff --git a/services/ans/test/unittest/BUILD.gn b/services/ans/test/unittest/BUILD.gn index b404f890741cb2724ac2c9b360bfa3b7cf0ed1d1..80690341eed4583efd8e91eaa6a55c492c615890 100644 --- a/services/ans/test/unittest/BUILD.gn +++ b/services/ans/test/unittest/BUILD.gn @@ -22,6 +22,9 @@ ohos_unittest("ans_unit_test") { include_dirs = [ ".", "include", + "//base/miscservices/time/interfaces/innerkits/include", + "//base/miscservices/time/services/time_manager/include", + "//base/miscservices/time/utils/native/include", "//foundation/appexecfwk/standard/libs/libeventhandler/src", "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", "//utils/native/base/include", @@ -47,6 +50,9 @@ ohos_unittest("ans_unit_test") { "${services_path}/ans/src/notification_slot_filter.cpp", "${services_path}/ans/src/notification_subscriber_manager.cpp", "${services_path}/ans/src/permission_filter.cpp", + "${services_path}/ans/src/reminder_data_manager.cpp", + "${services_path}/ans/src/reminder_event_manager.cpp", + "${services_path}/ans/src/reminder_timer_info.cpp", "${services_path}/ans/src/system_event_observer.cpp", "//foundation/distributeddatamgr/distributeddatamgr/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_snapshot.cpp", "//foundation/distributeddatamgr/distributeddatamgr/services/distributeddataservice/adapter/autils/src/constant.cpp", @@ -71,7 +77,10 @@ ohos_unittest("ans_unit_test") { "${core_path}:ans_core", "${frameworks_path}/ans/native:ans_innerkits", "${frameworks_path}/wantagent:wantagent_innerkits", + "//base/miscservices/time/services:time_service", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr:distributedschedsvr", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", "//third_party/googletest:gtest_main", "//utils/native/base:utils", diff --git a/services/test/moduletest/BUILD.gn b/services/test/moduletest/BUILD.gn index 0440b8b954218d7543558ba3c672d1067933bb75..f33bd200295362c5b3045d8667cf21b01fb361e5 100644 --- a/services/test/moduletest/BUILD.gn +++ b/services/test/moduletest/BUILD.gn @@ -21,6 +21,7 @@ ohos_moduletest("ans_module_test") { module_out_path = module_output_path include_dirs = [ "include", + "//base/miscservices/time/interfaces/innerkits/include", "//foundation/appexecfwk/standard/libs/libeventhandler/src", "//utils/native/base/include", "//utils/system/safwk/native/include", @@ -46,6 +47,9 @@ ohos_moduletest("ans_module_test") { "${services_path}/ans/src/notification_slot_filter.cpp", "${services_path}/ans/src/notification_subscriber_manager.cpp", "${services_path}/ans/src/permission_filter.cpp", + "${services_path}/ans/src/reminder_data_manager.cpp", + "${services_path}/ans/src/reminder_event_manager.cpp", + "${services_path}/ans/src/reminder_timer_info.cpp", "${services_path}/ans/src/system_event_observer.cpp", "//foundation/distributeddatamgr/distributeddatamgr/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_snapshot.cpp", "//foundation/distributeddatamgr/distributeddatamgr/services/distributeddataservice/adapter/autils/src/constant.cpp", @@ -65,11 +69,14 @@ ohos_moduletest("ans_module_test") { "${core_path}:ans_core", "${frameworks_path}/ans/native:ans_innerkits", "${frameworks_path}/wantagent:wantagent_innerkits", + "//base/miscservices/time/services:time_service", "//foundation/aafwk/standard/services/abilitymgr:abilityms", "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr:distributedschedsvr", "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native",