• 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_trace_wrapper.h"
30 #include "ans_inner_errors.h"
31 #include "os_account_manager.h"
32 #include "notification_helper.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     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
66     ANSR_LOGD("called");
67     sptr<ReminderRequest> tarReminder = CreateReminderRequest(reminder);
68     if (nullptr == tarReminder) {
69         ANSR_LOGE("null tarReminder");
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 = ReminderBundleManagerHelper::GetInstance().GetBundleNameByUid(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     return ret;
105 }
106 
UpdateReminder(const int32_t reminderId,const ReminderRequest & reminder)107 ErrCode ReminderAgentService::UpdateReminder(const int32_t reminderId, const ReminderRequest& reminder)
108 {
109     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
110     ANSR_LOGD("called");
111     sptr<ReminderRequest> tarReminder = CreateReminderRequest(reminder);
112     if (nullptr == tarReminder) {
113         ANSR_LOGE("null tarReminder");
114         return ERR_REMINDER_INVALID_PARAM;
115     }
116     if (!CheckReminderPermission()) {
117         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
118         return ERR_REMINDER_PERMISSION_DENIED;
119     }
120     int32_t callingUid = IPCSkeleton::GetCallingUid();
121     std::string bundleName = ReminderBundleManagerHelper::GetInstance().GetBundleNameByUid(callingUid);
122     ErrCode ret = InitReminderRequest(tarReminder, bundleName, callingUid);
123     if (ret != ERR_OK) {
124         return ret;
125     }
126     auto rdm = ReminderDataManager::GetInstance();
127     if (nullptr == rdm) {
128         return ERR_NO_INIT;
129     }
130     tarReminder->SetReminderId(reminderId);
131     ret = rdm->UpdateReminder(tarReminder, callingUid);
132     TryPostDelayUnloadTask(UNLOAD_TASK_DELAY_TIME);
133     return ret;
134 }
135 
CancelReminder(const int32_t reminderId)136 ErrCode ReminderAgentService::CancelReminder(const int32_t reminderId)
137 {
138     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
139     ANSR_LOGD("called");
140     if (!CheckReminderPermission()) {
141         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
142         return ERR_REMINDER_PERMISSION_DENIED;
143     }
144     auto rdm = ReminderDataManager::GetInstance();
145     if (nullptr == rdm) {
146         return ERR_NO_INIT;
147     }
148     ErrCode ret = rdm->CancelReminder(reminderId, IPCSkeleton::GetCallingUid());
149     return ret;
150 }
151 
CancelAllReminders()152 ErrCode ReminderAgentService::CancelAllReminders()
153 {
154     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
155     ANSR_LOGD("called");
156     if (!CheckReminderPermission()) {
157         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
158         return ERR_REMINDER_PERMISSION_DENIED;
159     }
160     auto rdm = ReminderDataManager::GetInstance();
161     if (nullptr == rdm) {
162         return ERR_NO_INIT;
163     }
164     int32_t callingUid = IPCSkeleton::GetCallingUid();
165     std::string bundleName = ReminderBundleManagerHelper::GetInstance().GetBundleNameByUid(callingUid);
166     int32_t userId = -1;
167     AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(callingUid, userId);
168     ErrCode ret = rdm->CancelAllReminders(bundleName, userId, callingUid);
169     return ret;
170 }
171 
GetValidReminders(std::vector<ReminderRequestAdaptation> & reminders)172 ErrCode ReminderAgentService::GetValidReminders(std::vector<ReminderRequestAdaptation>& reminders)
173 {
174     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
175     ANSR_LOGD("called");
176     if (!CheckReminderPermission()) {
177         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
178         return ERR_REMINDER_PERMISSION_DENIED;
179     }
180     auto rdm = ReminderDataManager::GetInstance();
181     if (nullptr == rdm) {
182         return ERR_NO_INIT;
183     }
184     reminders.clear();
185     rdm->GetValidReminders(IPCSkeleton::GetCallingUid(), reminders);
186     return ERR_OK;
187 }
188 
AddExcludeDate(const int32_t reminderId,const int64_t date)189 ErrCode ReminderAgentService::AddExcludeDate(const int32_t reminderId, const int64_t date)
190 {
191     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
192     ANSR_LOGD("called");
193     if (!CheckReminderPermission()) {
194         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
195         return ERR_REMINDER_PERMISSION_DENIED;
196     }
197     auto rdm = ReminderDataManager::GetInstance();
198     if (nullptr == rdm) {
199         return ERR_NO_INIT;
200     }
201     ErrCode ret = rdm->AddExcludeDate(reminderId, date, IPCSkeleton::GetCallingUid());
202     return ret;
203 }
204 
DelExcludeDates(const int32_t reminderId)205 ErrCode ReminderAgentService::DelExcludeDates(const int32_t reminderId)
206 {
207     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
208     ANSR_LOGD("called");
209     if (!CheckReminderPermission()) {
210         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
211         return ERR_REMINDER_PERMISSION_DENIED;
212     }
213     auto rdm = ReminderDataManager::GetInstance();
214     if (nullptr == rdm) {
215         return ERR_NO_INIT;
216     }
217     ErrCode ret = rdm->DelExcludeDates(reminderId, IPCSkeleton::GetCallingUid());
218     return ret;
219 }
220 
GetExcludeDates(const int32_t reminderId,std::vector<int64_t> & dates)221 ErrCode ReminderAgentService::GetExcludeDates(const int32_t reminderId, std::vector<int64_t>& dates)
222 {
223     NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
224     ANSR_LOGD("called");
225     if (!CheckReminderPermission()) {
226         ANSR_LOGE("Failed to check permission: ohos.permission.PUBLISH_AGENT_REMINDER.");
227         return ERR_REMINDER_PERMISSION_DENIED;
228     }
229     auto rdm = ReminderDataManager::GetInstance();
230     if (nullptr == rdm) {
231         return ERR_NO_INIT;
232     }
233     ErrCode ret = rdm->GetExcludeDates(reminderId, IPCSkeleton::GetCallingUid(), dates);
234     return ret;
235 }
236 
TryPostDelayUnloadTask(const int64_t delayTime)237 void ReminderAgentService::TryPostDelayUnloadTask(const int64_t delayTime)
238 {
239     std::lock_guard<std::mutex> locker(unloadMutex_);
240     if (nullptr != tryUnloadTask_) {
241         ffrt::skip(tryUnloadTask_);
242     }
243     tryUnloadTask_ = ffrt::submit_h([]() {
244         ReminderAgentService::GetInstance()->TryUnloadService();
245     }, {}, {}, ffrt::task_attr().delay(delayTime));
246 }
247 
TryUnloadService()248 void ReminderAgentService::TryUnloadService()
249 {
250     std::lock_guard<std::mutex> locker(unloadMutex_);
251     auto rdm = ReminderDataManager::GetInstance();
252     if (nullptr == rdm) {
253         tryUnloadTask_ = nullptr;
254         return;
255     }
256     int32_t reminderCount = rdm->QueryActiveReminderCount();
257     if (reminderCount > 0) {
258         tryUnloadTask_ = nullptr;
259         return;
260     }
261     ANSR_LOGD("called");
262     ChangeReminderAgentLoadConfig(REMINDER_AGENT_SERVICE_UNLOAD_STATE);
263     auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
264     if (samgrProxy == nullptr) {
265         ANSR_LOGE("null samgrProxy");
266         tryUnloadTask_ = nullptr;
267         return;
268     }
269     int32_t ret = samgrProxy->UnloadSystemAbility(REMINDER_AGENT_SERVICE_ID);
270     if (ret != ERR_OK) {
271         ANSR_LOGE("Failed to unload system ability.");
272     }
273     tryUnloadTask_ = nullptr;
274 }
275 
ChangeReminderAgentLoadConfig(const int8_t reminderAgentState)276 void ReminderAgentService::ChangeReminderAgentLoadConfig(const int8_t reminderAgentState)
277 {
278     if (reminderAgentState_ != reminderAgentState) {
279         OHOS::SaveStringToFile(REMINDER_AGENT_SERVICE_CONFIG_PATH, std::to_string(reminderAgentState), true);
280         reminderAgentState_ = reminderAgentState;
281     }
282 }
283 
CreateReminderRequest(const ReminderRequest & reminder)284 sptr<ReminderRequest> ReminderAgentService::CreateReminderRequest(const ReminderRequest& reminder)
285 {
286     sptr<ReminderRequest> tarReminder = nullptr;
287     switch (reminder.GetReminderType()) {
288         case ReminderRequest::ReminderType::TIMER: {
289             ANSR_LOGI("Publish timer.");
290             ReminderRequestTimer& timer = (ReminderRequestTimer&)reminder;
291             tarReminder = new (std::nothrow) ReminderRequestTimer(timer);
292             break;
293         }
294         case ReminderRequest::ReminderType::ALARM: {
295             ANSR_LOGI("Publish alarm.");
296             ReminderRequestAlarm& alarm = (ReminderRequestAlarm&)reminder;
297             tarReminder = new (std::nothrow) ReminderRequestAlarm(alarm);
298             break;
299         }
300         case ReminderRequest::ReminderType::CALENDAR: {
301             ANSR_LOGI("Publish calendar.");
302             ReminderRequestCalendar& calendar = (ReminderRequestCalendar&)reminder;
303             tarReminder = new (std::nothrow) ReminderRequestCalendar(calendar);
304             break;
305         }
306         default: {
307             ANSR_LOGW("Unknown reminder type.");
308             break;
309         }
310     }
311     return tarReminder;
312 }
313 
InitReminderRequest(sptr<ReminderRequest> & reminder,const std::string & bundle,const int32_t callingUid)314 ErrCode ReminderAgentService::InitReminderRequest(sptr<ReminderRequest>& reminder,
315     const std::string& bundle, const int32_t callingUid)
316 {
317     if (reminder->GetWantAgentInfo() == nullptr || reminder->GetMaxScreenWantAgentInfo() == nullptr) {
318         ANSR_LOGE("null WantAgentInfo");
319         return ERR_REMINDER_INVALID_PARAM;
320     }
321     std::string wantAgentName = reminder->GetWantAgentInfo()->pkgName;
322     std::string maxWantAgentName = reminder->GetMaxScreenWantAgentInfo()->pkgName;
323     if (wantAgentName != maxWantAgentName && wantAgentName != "" && maxWantAgentName != "") {
324         ANSR_LOGE("WantAgentName[%{public}s] is not same to maxWantAgentName[%{public}s].",
325             wantAgentName.c_str(), maxWantAgentName.c_str());
326         return ERR_REMINDER_INVALID_PARAM;
327     }
328     int32_t activeUserId = -1;
329     if (AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(activeUserId) != ERR_OK) {
330         ANSR_LOGE("Failed to get active user id.");
331         return ERR_REMINDER_INVALID_PARAM;
332     }
333     std::string bundleName = bundle;
334     int32_t uid = callingUid;
335     if (wantAgentName != bundle && wantAgentName != "") {
336         bundleName = wantAgentName;
337         uid = ReminderBundleManagerHelper::GetInstance().GetDefaultUidByBundleName(bundleName, activeUserId);
338     } else if (maxWantAgentName != bundle && maxWantAgentName != "") {
339         bundleName = maxWantAgentName;
340         uid = ReminderBundleManagerHelper::GetInstance().GetDefaultUidByBundleName(bundleName, activeUserId);
341     }
342     // Only system applications can proxy other applications to send notifications
343     bool isSystemApp = IsSystemApp();
344     if (bundleName != bundle && !isSystemApp) {
345         ANSR_LOGE("Only system applications can proxy other applications to send notifications.");
346         return ERR_REMINDER_INVALID_PARAM;
347     }
348     reminder->SetSystemApp(isSystemApp);
349     reminder->InitUserId(activeUserId);
350     reminder->InitBundleName(bundleName);
351     reminder->InitCreatorBundleName(bundle);
352     reminder->InitCreatorUid(callingUid);
353     reminder->InitUid(uid);
354     return ERR_OK;
355 }
356 
CheckReminderPermission()357 bool ReminderAgentService::CheckReminderPermission()
358 {
359     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
360     ErrCode ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(
361         callerToken, "ohos.permission.PUBLISH_AGENT_REMINDER");
362     return ret == Security::AccessToken::PermissionState::PERMISSION_GRANTED;
363 }
364 
IsSystemApp()365 bool ReminderAgentService::IsSystemApp()
366 {
367     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
368     Security::AccessToken::ATokenTypeEnum type = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
369     if (type != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
370         return false;
371     }
372     uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
373     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
374 }
375 }  // namespace OHOS::Notification
376