• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "reminder_agent_service.h"
17 
18 #include "reminder_data_manager.h"
19 #include "reminder_request_alarm.h"
20 #include "reminder_request_timer.h"
21 #include "reminder_request_calendar.h"
22 #include "reminder_bundle_manager_helper.h"
23 
24 #include "ffrt_inner.h"
25 #include "tokenid_kit.h"
26 #include "ipc_skeleton.h"
27 #include "accesstoken_kit.h"
28 #include "ans_log_wrapper.h"
29 #include "ans_inner_errors.h"
30 #include "os_account_manager.h"
31 #include "notification_helper.h"
32 #include "hitrace_meter_adapter.h"
33 #include "in_process_call_wrapper.h"
34 
35 #include <file_ex.h>
36 
37 namespace OHOS::Notification {
38 namespace {
39 constexpr int8_t REMINDER_AGENT_SERVICE_LOAD_STATE = 1;
40 constexpr int8_t REMINDER_AGENT_SERVICE_UNLOAD_STATE = 0;
41 constexpr int32_t REMINDER_AGENT_SERVICE_ID = 3204;
42 constexpr int64_t UNLOAD_TASK_DELAY_TIME = 60 * 1000 * 1000;  // 60s, ut: microsecond
43 constexpr const char* REMINDER_AGENT_SERVICE_CONFIG_PATH =
44     "/data/service/el1/public/notification/reminder_agent_service_config";
45 }
46 
47 std::mutex ReminderAgentService::instanceMutex_;
48 sptr<ReminderAgentService> ReminderAgentService::instance_;
49 
GetInstance()50 sptr<ReminderAgentService> ReminderAgentService::GetInstance()
51 {
52     std::lock_guard<std::mutex> locker(instanceMutex_);
53     if (instance_ == nullptr) {
54         instance_ = new (std::nothrow) ReminderAgentService();
55         if (instance_ == nullptr) {
56             ANSR_LOGE("Failed to create ReminderAgentService instance.");
57             return nullptr;
58         }
59     }
60     return instance_;
61 }
62 
PublishReminder(const ReminderRequest & reminder,int32_t & reminderId)63 ErrCode ReminderAgentService::PublishReminder(const ReminderRequest& reminder, int32_t& reminderId)
64 {
65     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
66     ANSR_LOGD("call.");
67     sptr<ReminderRequest> tarReminder = CreateReminderRequest(reminder);
68     if (nullptr == tarReminder) {
69         ANSR_LOGE("Failed to create ReminderRequest.");
70         return ERR_REMINDER_INVALID_PARAM;
71     }
72     if (!CheckReminderPermission()) {
73         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
74         return ERR_REMINDER_PERMISSION_DENIED;
75     }
76     int32_t callingUid = IPCSkeleton::GetCallingUid();
77     std::string bundleName = GetClientBundleName(callingUid);
78     bool isAllowUseReminder = false;
79     NotificationHelper::AllowUseReminder(bundleName, isAllowUseReminder);
80     if (!isAllowUseReminder) {
81         ANSR_LOGW("The number of reminders exceeds the limit[0].");
82         return ERR_REMINDER_NUMBER_OVERLOAD;
83     }
84     ErrCode ret = InitReminderRequest(tarReminder, bundleName, callingUid);
85     if (ret != ERR_OK) {
86         return ret;
87     }
88     NotificationBundleOption bundleOption(tarReminder->GetBundleName(), tarReminder->GetUid());
89     bool allowedNotify = false;
90     ret = IN_PROCESS_CALL(NotificationHelper::IsAllowedNotify(bundleOption, allowedNotify));
91     if (!tarReminder->IsSystemApp() && (ret != ERR_OK || !allowedNotify)) {
92         ANSR_LOGW("The application does not request enable notification.");
93         return ERR_REMINDER_NOTIFICATION_NOT_ENABLE;
94     }
95     auto rdm = ReminderDataManager::GetInstance();
96     if (nullptr == rdm) {
97         return ERR_NO_INIT;
98     }
99     ret = rdm->PublishReminder(tarReminder, callingUid);
100     if (ret == ERR_OK) {
101         reminderId = tarReminder->GetReminderId();
102         ChangeReminderAgentLoadConfig(REMINDER_AGENT_SERVICE_LOAD_STATE);
103     }
104     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
105     return ret;
106 }
107 
CancelReminder(const int32_t reminderId)108 ErrCode ReminderAgentService::CancelReminder(const int32_t reminderId)
109 {
110     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
111     ANSR_LOGD("call.");
112     if (!CheckReminderPermission()) {
113         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
114         return ERR_REMINDER_PERMISSION_DENIED;
115     }
116     auto rdm = ReminderDataManager::GetInstance();
117     if (nullptr == rdm) {
118         return ERR_NO_INIT;
119     }
120     ErrCode ret = rdm->CancelReminder(reminderId, IPCSkeleton::GetCallingUid());
121     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
122     return ret;
123 }
124 
CancelAllReminders()125 ErrCode ReminderAgentService::CancelAllReminders()
126 {
127     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
128     ANSR_LOGD("call.");
129     if (!CheckReminderPermission()) {
130         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
131         return ERR_REMINDER_PERMISSION_DENIED;
132     }
133     auto rdm = ReminderDataManager::GetInstance();
134     if (nullptr == rdm) {
135         return ERR_NO_INIT;
136     }
137     int32_t callingUid = IPCSkeleton::GetCallingUid();
138     std::string bundleName = GetClientBundleName(callingUid);
139     int32_t userId = -1;
140     AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(callingUid, userId);
141     ErrCode ret = rdm->CancelAllReminders(bundleName, userId, callingUid);
142     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
143     return ret;
144 }
145 
GetValidReminders(std::vector<ReminderRequestAdaptation> & reminders)146 ErrCode ReminderAgentService::GetValidReminders(std::vector<ReminderRequestAdaptation>& reminders)
147 {
148     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
149     ANSR_LOGD("call.");
150     if (!CheckReminderPermission()) {
151         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
152         return ERR_REMINDER_PERMISSION_DENIED;
153     }
154     auto rdm = ReminderDataManager::GetInstance();
155     if (nullptr == rdm) {
156         return ERR_NO_INIT;
157     }
158     reminders.clear();
159     rdm->GetValidReminders(IPCSkeleton::GetCallingUid(), reminders);
160     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
161     return ERR_OK;
162 }
163 
AddExcludeDate(const int32_t reminderId,const int64_t date)164 ErrCode ReminderAgentService::AddExcludeDate(const int32_t reminderId, const int64_t date)
165 {
166     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
167     ANSR_LOGD("call.");
168     if (!CheckReminderPermission()) {
169         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
170         return ERR_REMINDER_PERMISSION_DENIED;
171     }
172     auto rdm = ReminderDataManager::GetInstance();
173     if (nullptr == rdm) {
174         return ERR_NO_INIT;
175     }
176     ErrCode ret = rdm->AddExcludeDate(reminderId, date, IPCSkeleton::GetCallingUid());
177     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
178     return ret;
179 }
180 
DelExcludeDates(const int32_t reminderId)181 ErrCode ReminderAgentService::DelExcludeDates(const int32_t reminderId)
182 {
183     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
184     ANSR_LOGD("call.");
185     if (!CheckReminderPermission()) {
186         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
187         return ERR_REMINDER_PERMISSION_DENIED;
188     }
189     auto rdm = ReminderDataManager::GetInstance();
190     if (nullptr == rdm) {
191         return ERR_NO_INIT;
192     }
193     ErrCode ret = rdm->DelExcludeDates(reminderId, IPCSkeleton::GetCallingUid());
194     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
195     return ret;
196 }
197 
GetExcludeDates(const int32_t reminderId,std::vector<int64_t> & dates)198 ErrCode ReminderAgentService::GetExcludeDates(const int32_t reminderId, std::vector<int64_t>& dates)
199 {
200     HITRACE_METER_NAME(HITRACE_TAG_OHOS, __PRETTY_FUNCTION__);
201     ANSR_LOGD("call.");
202     if (!CheckReminderPermission()) {
203         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
204         return ERR_REMINDER_PERMISSION_DENIED;
205     }
206     auto rdm = ReminderDataManager::GetInstance();
207     if (nullptr == rdm) {
208         return ERR_NO_INIT;
209     }
210     ErrCode ret = rdm->GetExcludeDates(reminderId, IPCSkeleton::GetCallingUid(), dates);
211     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
212     return ret;
213 }
214 
TryPostDelayUnloadTask(const int64_t delayTime)215 void ReminderAgentService::TryPostDelayUnloadTask(const int64_t delayTime)
216 {
217     std::lock_guard<std::mutex> locker(unloadMutex_);
218     if (nullptr != tryUnloadTask_) {
219         ffrt::skip(tryUnloadTask_);
220     }
221     tryUnloadTask_ = ffrt::submit_h([]() {
222         ReminderAgentService::GetInstance()->TryUnloadService();
223     }, {}, {}, ffrt::task_attr().delay(delayTime));
224 }
225 
TryUnloadService()226 void ReminderAgentService::TryUnloadService()
227 {
228     std::lock_guard<std::mutex> locker(unloadMutex_);
229     auto rdm = ReminderDataManager::GetInstance();
230     if (nullptr == rdm) {
231         tryUnloadTask_ = nullptr;
232         return;
233     }
234     int32_t reminderCount = rdm->QueryActiveReminderCount();
235     if (reminderCount > 0) {
236         tryUnloadTask_ = nullptr;
237         return;
238     }
239     ANSR_LOGD("do unload task");
240     ChangeReminderAgentLoadConfig(REMINDER_AGENT_SERVICE_UNLOAD_STATE);
241     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
242     if (samgrProxy == nullptr) {
243         ANSR_LOGE("Failed to get samgr.");
244         tryUnloadTask_ = nullptr;
245         return;
246     }
247     int32_t ret = samgrProxy->UnloadSystemAbility(REMINDER_AGENT_SERVICE_ID);
248     if (ret != ERR_OK) {
249         ANSR_LOGE("Failed to unload system ability.");
250     }
251     tryUnloadTask_ = nullptr;
252 }
253 
ChangeReminderAgentLoadConfig(const int8_t reminderAgentState)254 void ReminderAgentService::ChangeReminderAgentLoadConfig(const int8_t reminderAgentState)
255 {
256     if (reminderAgentState_ != reminderAgentState) {
257         OHOS::SaveStringToFile(REMINDER_AGENT_SERVICE_CONFIG_PATH, std::to_string(reminderAgentState), true);
258         reminderAgentState_ = reminderAgentState;
259     }
260 }
261 
CreateReminderRequest(const ReminderRequest & reminder)262 sptr<ReminderRequest> ReminderAgentService::CreateReminderRequest(const ReminderRequest& reminder)
263 {
264     sptr<ReminderRequest> tarReminder = nullptr;
265     switch (reminder.GetReminderType()) {
266         case ReminderRequest::ReminderType::TIMER: {
267             ANSR_LOGI("Publish timer.");
268             ReminderRequestTimer& timer = (ReminderRequestTimer&)reminder;
269             tarReminder = new (std::nothrow) ReminderRequestTimer(timer);
270             break;
271         }
272         case ReminderRequest::ReminderType::ALARM: {
273             ANSR_LOGI("Publish alarm.");
274             ReminderRequestAlarm& alarm = (ReminderRequestAlarm&)reminder;
275             tarReminder = new (std::nothrow) ReminderRequestAlarm(alarm);
276             break;
277         }
278         case ReminderRequest::ReminderType::CALENDAR: {
279             ANSR_LOGI("Publish calendar.");
280             ReminderRequestCalendar& calendar = (ReminderRequestCalendar&)reminder;
281             tarReminder = new (std::nothrow) ReminderRequestCalendar(calendar);
282             break;
283         }
284         default: {
285             ANSR_LOGW("Unknown reminder type.");
286             break;
287         }
288     }
289     return tarReminder;
290 }
291 
InitReminderRequest(sptr<ReminderRequest> & reminder,const std::string & bundle,const int32_t callingUid)292 ErrCode ReminderAgentService::InitReminderRequest(sptr<ReminderRequest>& reminder,
293     const std::string& bundle, const int32_t callingUid)
294 {
295     if (reminder->GetWantAgentInfo() == nullptr || reminder->GetMaxScreenWantAgentInfo() == nullptr) {
296         ANSR_LOGE("WantAgentInfo is nullptr.");
297         return ERR_REMINDER_INVALID_PARAM;
298     }
299     std::string wantAgentName = reminder->GetWantAgentInfo()->pkgName;
300     std::string maxWantAgentName = reminder->GetMaxScreenWantAgentInfo()->pkgName;
301     if (wantAgentName != maxWantAgentName && wantAgentName != "" && maxWantAgentName != "") {
302         ANSR_LOGE("WantAgentName[%{public}s] is not same to maxWantAgentName[%{public}s].",
303             wantAgentName.c_str(), maxWantAgentName.c_str());
304         return ERR_REMINDER_INVALID_PARAM;
305     }
306     int32_t activeUserId = -1;
307     if (AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(activeUserId) != ERR_OK) {
308         ANSR_LOGE("Failed to get active user id.");
309         return ERR_REMINDER_INVALID_PARAM;
310     }
311     std::shared_ptr<ReminderBundleManagerHelper> bundleMgr = ReminderBundleManagerHelper::GetInstance();
312     if (nullptr == bundleMgr) {
313         ANSR_LOGE("Failed to bundle manager.");
314         return ERR_REMINDER_INVALID_PARAM;
315     }
316     std::string bundleName = bundle;
317     int32_t uid = callingUid;
318     if (wantAgentName != bundle && wantAgentName != "") {
319         bundleName = wantAgentName;
320         uid = bundleMgr->GetDefaultUidByBundleName(bundleName, activeUserId);
321     } else if (maxWantAgentName != bundle && maxWantAgentName != "") {
322         bundleName = maxWantAgentName;
323         uid = bundleMgr->GetDefaultUidByBundleName(bundleName, activeUserId);
324     }
325     // Only system applications can proxy other applications to send notifications
326     bool isSystemApp = IsSystemApp();
327     if (bundleName != bundle && !isSystemApp) {
328         ANSR_LOGE("Only system applications can proxy other applications to send notifications.");
329         return ERR_REMINDER_INVALID_PARAM;
330     }
331     reminder->SetSystemApp(isSystemApp);
332     reminder->InitUserId(activeUserId);
333     reminder->InitBundleName(bundleName);
334     reminder->InitCreatorBundleName(bundle);
335     reminder->InitCreatorUid(callingUid);
336     reminder->InitUid(uid);
337     return ERR_OK;
338 }
339 
CheckReminderPermission()340 bool ReminderAgentService::CheckReminderPermission()
341 {
342     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
343     ErrCode ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(
344         callerToken, "ohos.permission.PUBLISH_AGENT_REMINDER");
345     return ret == Security::AccessToken::PermissionState::PERMISSION_GRANTED;
346 }
347 
IsSystemApp()348 bool ReminderAgentService::IsSystemApp()
349 {
350     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
351     Security::AccessToken::ATokenTypeEnum type = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
352     if (type != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
353         return false;
354     }
355     uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
356     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
357 }
358 
GetClientBundleName(const int32_t callingUid)359 std::string ReminderAgentService::GetClientBundleName(const int32_t callingUid)
360 {
361     std::string bundleName;
362     std::shared_ptr<ReminderBundleManagerHelper> bundleMgr = ReminderBundleManagerHelper::GetInstance();
363     if (bundleMgr != nullptr) {
364         bundleName = bundleMgr->GetBundleNameByUid(callingUid);
365     }
366     return bundleName;
367 }
368 }  // namespace OHOS::Notification
369