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