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