1 /*
2 * Copyright (c) 2024-2024 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_data_manager.h"
17
18 #include "ability_manager_client.h"
19 #include "ans_log_wrapper.h"
20 #include "ans_trace_wrapper.h"
21 #include "ans_const_define.h"
22 #include "common_event_support.h"
23 #include "common_event_manager.h"
24 #include "reminder_request_calendar.h"
25 #include "in_process_call_wrapper.h"
26 #include "ipc_skeleton.h"
27 #include "notification_slot.h"
28 #include "os_account_manager.h"
29 #include "reminder_event_manager.h"
30 #include "time_service_client.h"
31 #include "singleton.h"
32 #include "locale_config.h"
33 #include "datashare_predicates_object.h"
34 #include "datashare_value_object.h"
35 #include "datashare_helper.h"
36 #include "data_share_permission.h"
37 #include "datashare_errno.h"
38 #include "datashare_template.h"
39 #include "system_ability_definition.h"
40 #include "app_mgr_constants.h"
41 #include "iservice_registry.h"
42 #include "config_policy_utils.h"
43 #include "hitrace_meter_adapter.h"
44 #include "notification_helper.h"
45 #include "reminder_datashare_helper.h"
46 #ifdef HAS_HISYSEVENT_PART
47 #include <sys/statfs.h>
48 #include "hisysevent.h"
49 #include "reminder_utils.h"
50 #include "directory_ex.h"
51 #endif
52
53 namespace OHOS {
54 namespace Notification {
55 namespace {
56 constexpr int32_t ALL_SA_READY_FLAG = 2; // bundle service and ability service ready.
57 // The maximum number of applications that can be displayed at a time
58 constexpr int32_t ONE_HAP_MAX_NUMBER_SHOW_AT_ONCE = 10;
59 // The maximum number of system that can be displayed at a time
60 constexpr int32_t TOTAL_MAX_NUMBER_SHOW_AT_ONCE = 500;
61 // The maximun number of system that can be start extension count
62 constexpr int32_t TOTAL_MAX_NUMBER_START_EXTENSION = 100;
63 constexpr int32_t CONNECT_EXTENSION_INTERVAL = 100;
64 static constexpr const char* USER_SETINGS_DATA_SECURE_URI =
65 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_";
66 static constexpr const char* FOCUS_MODE_ENABLE_URI = "?Proxy=true&key=focus_mode_enable";
67 static constexpr const char* FOCUS_MODE_ENABLE = "focus_mode_enable";
68 }
69
GetRemainPartitionSize(const std::string & partitionName)70 static uint64_t GetRemainPartitionSize(const std::string& partitionName)
71 {
72 #ifdef HAS_HISYSEVENT_PART
73 struct statfs stat;
74 if (statfs(partitionName.c_str(), &stat) != 0) {
75 return -1;
76 }
77 uint64_t blockSize = stat.f_bsize;
78 uint64_t freeSize = stat.f_bfree * blockSize;
79 constexpr double units = 1024.0;
80 return freeSize/(units * units);
81 #else
82 return 0;
83 #endif
84 }
85
GetFileOrFolderSize(const std::vector<std::string> & paths)86 static std::vector<uint64_t> GetFileOrFolderSize(const std::vector<std::string>& paths)
87 {
88 std::vector<uint64_t> folderSize;
89 #ifdef HAS_HISYSEVENT_PART
90 for (auto path : paths) {
91 folderSize.emplace_back(OHOS::GetFolderSize(path));
92 }
93 #endif
94 return folderSize;
95 }
96
IsSystemReady()97 bool ReminderDataManager::IsSystemReady()
98 {
99 return saReadyFlag_ >= ALL_SA_READY_FLAG;
100 }
101
IsActionButtonDataShareValid(const sptr<ReminderRequest> & reminder,const uint32_t callerTokenId)102 bool ReminderDataManager::IsActionButtonDataShareValid(const sptr<ReminderRequest>& reminder,
103 const uint32_t callerTokenId)
104 {
105 auto actionButtonMap = reminder->GetActionButtons();
106 for (auto it = actionButtonMap.begin(); it != actionButtonMap.end(); ++it) {
107 ReminderRequest::ActionButtonInfo& buttonInfo = it->second;
108 if (buttonInfo.dataShareUpdate->uri.empty()) {
109 continue;
110 }
111 Uri uri(buttonInfo.dataShareUpdate->uri);
112 auto ret = DataShare::DataSharePermission::VerifyPermission(callerTokenId, uri, false);
113 if (ret != DataShare::E_OK) {
114 ANSR_LOGE("publish failed, DataSharePermission::VerifyPermission return error[%{public}d],",
115 static_cast<int32_t>(ret));
116 return false;
117 }
118 }
119 return true;
120 }
121
HandleAutoDeleteReminder(const int32_t notificationId,const int32_t uid,const int64_t autoDeletedTime)122 void ReminderDataManager::HandleAutoDeleteReminder(const int32_t notificationId, const int32_t uid,
123 const int64_t autoDeletedTime)
124 {
125 ANSR_LOGD("called");
126 std::vector<sptr<ReminderRequest>> showedReminder;
127 {
128 std::lock_guard<std::mutex> lock(ReminderDataManager::SHOW_MUTEX);
129 showedReminder = showedReminderVector_;
130 }
131 for (auto reminder : showedReminder) {
132 if (reminder == nullptr) {
133 continue;
134 }
135
136 if (reminder->GetUid() != uid || notificationId != reminder->GetNotificationId() ||
137 reminder->GetAutoDeletedTime() != autoDeletedTime) {
138 continue;
139 }
140 CloseReminder(reminder, true);
141 UpdateAppDatabase(reminder, ReminderRequest::ActionButtonType::CLOSE);
142 CheckNeedNotifyStatus(reminder, ReminderRequest::ActionButtonType::CLOSE);
143 }
144 StartRecentReminder();
145 }
146
OnBundleMgrServiceStart()147 void ReminderDataManager::OnBundleMgrServiceStart()
148 {
149 saReadyFlag_.fetch_add(1);
150 }
151
OnAbilityMgrServiceStart()152 void ReminderDataManager::OnAbilityMgrServiceStart()
153 {
154 saReadyFlag_.fetch_add(1);
155 }
156
GetCustomRingFileDesc(const sptr<ReminderRequest> & reminder,Global::Resource::ResourceManager::RawFileDescriptor & desc)157 bool ReminderDataManager::GetCustomRingFileDesc(const sptr<ReminderRequest>& reminder,
158 Global::Resource::ResourceManager::RawFileDescriptor& desc)
159 {
160 // obtains the resource manager
161 std::lock_guard<std::mutex> locker(resourceMutex_);
162 soundResource_ = GetResourceMgr(reminder->GetBundleName(), reminder->GetUid());
163 if (soundResource_ == nullptr) {
164 ANSR_LOGE("null soundResource");
165 return false;
166 }
167 auto result = soundResource_->GetRawFileDescriptor(reminder->GetCustomRingUri(), desc);
168 if (result != Global::Resource::SUCCESS) {
169 ANSR_LOGE("GetRawFileDescriptor fail[%{public}d].", static_cast<int32_t>(result));
170 return false;
171 }
172 return true;
173 }
174
CloseCustomRingFileDesc(const int32_t reminderId,const std::string & customRingUri)175 void ReminderDataManager::CloseCustomRingFileDesc(const int32_t reminderId, const std::string& customRingUri)
176 {
177 std::lock_guard<std::mutex> locker(resourceMutex_);
178 if (soundResource_ == nullptr) {
179 ANSR_LOGE("null soundResource");
180 return;
181 }
182 auto result = soundResource_->CloseRawFileDescriptor(customRingUri);
183 if (result != Global::Resource::SUCCESS) {
184 ANSR_LOGE("CloseRawFileDescriptor fail[%{public}d]", static_cast<int32_t>(result));
185 }
186 ANSR_LOGI("reminderId:[%{public}d]", reminderId);
187 soundResource_ = nullptr;
188 }
189
ReportSysEvent(const sptr<ReminderRequest> & reminder)190 void ReminderDataManager::ReportSysEvent(const sptr<ReminderRequest>& reminder)
191 {
192 #ifdef HAS_HISYSEVENT_PART
193 std::string event = "ALARM_TRIGGER";
194 std::string bundleName = reminder->GetBundleName();
195 int32_t uid = reminder->GetUid();
196 int32_t type = static_cast<int32_t>(reminder->GetReminderType());
197 int32_t repeat = static_cast<int32_t>(reminder->IsRepeat());
198 uint64_t triggerTime = reminder->GetTriggerTimeInMilli();
199 int32_t ringTime = static_cast<int32_t>(reminder->GetRingDuration());
200 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::NOTIFICATION, event, HiviewDFX::HiSysEvent::EventType::STATISTIC,
201 "UID", uid, "NAME", bundleName, "TYPE", type, "REPEAT", repeat, "TRIGGER_TIME", triggerTime,
202 "RING_TIME", ringTime);
203 #endif
204 }
205
CheckShowLimit(std::unordered_map<std::string,int32_t> & limits,int32_t & totalCount,sptr<ReminderRequest> & reminder)206 bool ReminderDataManager::CheckShowLimit(std::unordered_map<std::string, int32_t>& limits, int32_t& totalCount,
207 sptr<ReminderRequest>& reminder)
208 {
209 if (totalCount > TOTAL_MAX_NUMBER_SHOW_AT_ONCE) {
210 ANSR_LOGE("The maximum number of displays that can be displayed at a time has been reached.");
211 return false;
212 }
213 ++totalCount;
214 std::string key = std::to_string(reminder->GetUid()) + "_" + std::to_string(reminder->GetTriggerTimeInMilli());
215 auto iter = limits.find(key);
216 if (iter == limits.end()) {
217 limits[key] = 1;
218 return true;
219 }
220 if (iter->second > ONE_HAP_MAX_NUMBER_SHOW_AT_ONCE) {
221 ANSR_LOGE("The maximum number of displays that can be displayed in a single app[%{public}s] has been reached",
222 reminder->GetBundleName().c_str());
223 return false;
224 }
225 ++iter->second;
226 return true;
227 }
228
OnDataShareInsertOrDelete()229 void ReminderDataManager::OnDataShareInsertOrDelete()
230 {
231 LoadShareReminders();
232 std::vector<sptr<ReminderRequest>> immediatelyReminders;
233 std::vector<sptr<ReminderRequest>> extensionReminders;
234 CheckReminderTime(immediatelyReminders, extensionReminders);
235 HandleImmediatelyShow(immediatelyReminders, false);
236 StartRecentReminder();
237 }
238
OnDataShareUpdate(const std::map<std::string,sptr<ReminderRequest>> & reminders)239 void ReminderDataManager::OnDataShareUpdate(const std::map<std::string, sptr<ReminderRequest>>& reminders)
240 {
241 UpdateShareReminders(reminders);
242 }
243
UpdateShareReminders(const std::map<std::string,sptr<ReminderRequest>> & reminders)244 void ReminderDataManager::UpdateShareReminders(const std::map<std::string, sptr<ReminderRequest>>& reminders)
245 {
246 std::lock_guard<std::mutex> locker(ReminderDataManager::MUTEX);
247 for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) {
248 if (!(*it)->IsShare() || (*it)->GetReminderType() != ReminderRequest::ReminderType::CALENDAR) {
249 continue;
250 }
251 int32_t reminderId = (*it)->GetReminderId();
252 std::string identifier = (*it)->GetIdentifier();
253 auto iter = reminders.find(identifier);
254 if (iter == reminders.end()) {
255 continue;
256 }
257 ReminderRequestCalendar* calendar = static_cast<ReminderRequestCalendar*>((*it).GetRefPtr());
258 calendar->Copy(iter->second);
259 if ((*it)->IsShowing()) {
260 ShowReminder((*it), false, false, false, false, false);
261 }
262 }
263 }
264
AsyncStartExtensionAbility(const sptr<ReminderRequest> & reminder,int32_t times,const int8_t type,int32_t & count)265 void ReminderDataManager::AsyncStartExtensionAbility(const sptr<ReminderRequest> &reminder, int32_t times,
266 const int8_t type, int32_t& count)
267 {
268 auto manager = ReminderDataManager::GetInstance();
269 if (manager == nullptr) {
270 ANSR_LOGE("null manager");
271 return;
272 }
273 if (!manager->IsSystemReady()) {
274 ANSR_LOGE("bundle service or ability service not ready.");
275 return;
276 }
277 if (!reminder->IsSystemApp()) {
278 ANSR_LOGE("Start extension ability failed, is not system app");
279 return;
280 }
281 if (count > TOTAL_MAX_NUMBER_START_EXTENSION) {
282 ANSR_LOGE("The maximum number of start extension has been reached.");
283 return;
284 }
285 ++count;
286 times--;
287 bool ret = ReminderDataManager::StartExtensionAbility(reminder, type);
288 if (!ret && times > 0 && serviceQueue_ != nullptr) {
289 ANSR_LOGD("StartExtensionAbilty failed, reminder times: %{public}d", times);
290 ffrt::task_attr taskAttr;
291 taskAttr.delay(CONNECT_EXTENSION_INTERVAL);
292 auto callback = [reminder, times, type]() {
293 int32_t count = 0;
294 ReminderDataManager::AsyncStartExtensionAbility(reminder, times, type, count);
295 };
296 serviceQueue_->submit(callback, taskAttr);
297 }
298 }
299
UpdateReminderFromDb(const std::vector<sptr<ReminderRequest>> & remindersFromDb)300 void ReminderDataManager::UpdateReminderFromDb(const std::vector<sptr<ReminderRequest>>& remindersFromDb)
301 {
302 std::map<int32_t, sptr<ReminderRequest>> reminders;
303 for (const auto& reminder : remindersFromDb) {
304 reminders[reminder->GetReminderId()] = reminder;
305 }
306 // Only alerts that do not exist in memory are processed
307 for (const auto& reminder : reminderVector_) {
308 if (reminder->IsShare()) {
309 continue;
310 }
311 int32_t reminderId = reminder->GetReminderId();
312 auto iter = reminders.find(reminderId);
313 if (iter != reminders.end()) {
314 reminders.erase(iter);
315 }
316 }
317 // new reminder
318 for (auto& each : reminders) {
319 reminderVector_.push_back(each.second);
320 }
321 }
322
UpdateReminder(const sptr<ReminderRequest> & reminder,const int32_t callingUid)323 ErrCode ReminderDataManager::UpdateReminder(const sptr<ReminderRequest>& reminder, const int32_t callingUid)
324 {
325 NOTIFICATION_HITRACE(HITRACE_TAG_OHOS);
326 sptr<ReminderRequest> reminderOld = FindReminderRequestLocked(reminder->GetReminderId(), false);
327 bool existInMemory = true;
328 if (nullptr != reminderOld) {
329 if (!CheckIsSameApp(reminderOld, callingUid)) {
330 ANSR_LOGW("Not find the reminder due to not match");
331 return ERR_REMINDER_NOT_EXIST;
332 }
333 if (reminderOld->IsShowing()) {
334 ANSR_LOGW("Reminder already showing, update reminder failed.");
335 return ERR_REMINDER_NOT_EXIST;
336 }
337 } else {
338 existInMemory = false;
339 std::lock_guard<std::mutex> lock(ReminderDataManager::MUTEX);
340 if (!store_->IsReminderExist(reminder->GetReminderId(), reminder->GetCreatorUid())) {
341 ANSR_LOGW("Reminder not find, update reminder failed.");
342 return ERR_REMINDER_NOT_EXIST;
343 }
344 }
345 uint32_t callerTokenId = IPCSkeleton::GetCallingTokenID();
346 if (callerTokenId == 0) {
347 ANSR_LOGE("pushlish failed, callerTokenId is 0");
348 return ERR_REMINDER_CALLER_TOKEN_INVALID;
349 }
350 if (!IsActionButtonDataShareValid(reminder, callerTokenId)) {
351 return ERR_REMINDER_DATA_SHARE_PERMISSION_DENIED;
352 }
353
354 UpdateAndSaveReminderLocked(reminder, existInMemory);
355 queue_->submit([this, reminder]() {
356 StartRecentReminder();
357 });
358 return ERR_OK;
359 }
360
UpdateAndSaveReminderLocked(const sptr<ReminderRequest> & reminder,const bool isInMemory)361 void ReminderDataManager::UpdateAndSaveReminderLocked(const sptr<ReminderRequest>& reminder, const bool isInMemory)
362 {
363 std::lock_guard<std::mutex> lock(ReminderDataManager::MUTEX);
364 if (reminder->GetTriggerTimeInMilli() == ReminderRequest::INVALID_LONG_LONG_VALUE) {
365 ANSR_LOGW("now publish reminder is expired. reminder is =%{public}s", reminder->Dump().c_str());
366 reminder->SetExpired(true);
367 }
368 if (isInMemory) {
369 for (auto it = reminderVector_.begin(); it != reminderVector_.end(); ++it) {
370 if (reminder->GetReminderId() == (*it)->GetReminderId() && !(*it)->IsShare()) {
371 *it = reminder;
372 break;
373 }
374 }
375 } else {
376 reminderVector_.push_back(reminder);
377 }
378 store_->UpdateOrInsert(reminder);
379 }
380
SetActiveReminder(const sptr<ReminderRequest> & reminder)381 void ReminderDataManager::SetActiveReminder(const sptr<ReminderRequest> &reminder)
382 {
383 if (reminder == nullptr) {
384 // activeReminder_ should not be set with null as it point to actual object.
385 activeReminderId_ = -1;
386 activeTriggerTime_ = 0;
387 } else {
388 activeReminderId_ = reminder->GetReminderId();
389 activeTriggerTime_ = reminder->GetTriggerTimeInMilli();
390 std::lock_guard<std::mutex> locker(ReminderDataManager::ACTIVE_MUTEX);
391 activeReminder_ = reminder;
392 }
393 ANSR_LOGD("Set activeReminderId=%{public}d", activeReminderId_.load());
394 }
395
SetAlertingReminder(const sptr<ReminderRequest> & reminder)396 void ReminderDataManager::SetAlertingReminder(const sptr<ReminderRequest> &reminder)
397 {
398 if (reminder == nullptr) {
399 // alertingReminder_ should not be set with null as it point to actual object.
400 alertingReminderId_ = -1;
401 } else {
402 alertingReminderId_ = reminder->GetReminderId();
403 alertingReminder_ = reminder;
404 }
405 ANSR_LOGD("Set alertingReminderId=%{public}d", alertingReminderId_.load());
406 }
407
CancelReminderToDb(const int32_t reminderId,const int32_t callingUid)408 ErrCode ReminderDataManager::CancelReminderToDb(const int32_t reminderId, const int32_t callingUid)
409 {
410 if (store_ == nullptr) {
411 ANSR_LOGE("null store");
412 return ERR_REMINDER_NOT_EXIST;
413 }
414 std::lock_guard<std::mutex> lock(ReminderDataManager::MUTEX);
415 if (!store_->IsReminderExist(reminderId, callingUid)) {
416 ANSR_LOGE("Not find reminder[%{public}d] in db.", reminderId);
417 return ERR_REMINDER_NOT_EXIST;
418 }
419 store_->Delete(reminderId);
420 return ERR_OK;
421 }
422
IsAllowedNotify(const sptr<ReminderRequest> & reminder) const423 bool ReminderDataManager::IsAllowedNotify(const sptr<ReminderRequest> &reminder) const
424 {
425 if (reminder == nullptr) {
426 return false;
427 }
428 bool isAllowed = false;
429 NotificationBundleOption bundleOption(reminder->GetBundleName(), reminder->GetUid());
430 ErrCode errCode = IN_PROCESS_CALL(NotificationHelper::IsAllowedNotify(bundleOption, isAllowed));
431 if (errCode != ERR_OK) {
432 ANSR_LOGE("Failed to call IsAllowedNotify, errCode=%{public}d", errCode);
433 return false;
434 }
435 return isAllowed;
436 }
437
ReportTimerEvent(const int64_t targetTime,const bool isSysTimeChanged)438 void ReminderDataManager::ReportTimerEvent(const int64_t targetTime, const bool isSysTimeChanged)
439 {
440 #ifdef HAS_HISYSEVENT_PART
441 if (targetTime == 0) {
442 return;
443 }
444 constexpr int64_t deviation = 1000 * 60; // 1min
445 int64_t now = GetCurrentTime();
446 if ((now - targetTime) <= deviation) {
447 return;
448 }
449 uint8_t errorCode = isSysTimeChanged ? 0 : 1;
450 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::NOTIFICATION, "REMINDER_TIMER_ERROR",
451 HiviewDFX::HiSysEvent::EventType::STATISTIC,
452 "TARGET_TIME", targetTime, "TRIGGER_TIME", now, "ERROR_CODE", errorCode);
453 #endif
454 }
455
ReportUserDataSizeEvent()456 void ReminderDataManager::ReportUserDataSizeEvent()
457 {
458 #ifdef HAS_HISYSEVENT_PART
459 std::vector<std::string> paths = {
460 "/data/service/el1/public/notification/"
461 };
462 uint64_t remainPartitionSize = GetRemainPartitionSize("/data");
463 std::vector<uint64_t> folderSize = GetFileOrFolderSize(paths);
464 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FILEMANAGEMENT, "USER_DATA_SIZE",
465 HiviewDFX::HiSysEvent::EventType::STATISTIC,
466 "COMPONENT_NAME", "resource_schedule_service",
467 "PARTITION_NAME", "/data",
468 "REMAIN_PARTITION_SIZE", remainPartitionSize,
469 "FILE_OR_FOLDER_PATH", paths,
470 "FILE_OR_FOLDER_SIZE", folderSize);
471 #endif
472 }
473
CheckSoundConfig(const sptr<ReminderRequest> reminder)474 bool ReminderDataManager::CheckSoundConfig(const sptr<ReminderRequest> reminder)
475 {
476 #ifdef PLAYER_FRAMEWORK_ENABLE
477 NotificationBundleOption option;
478 option.SetBundleName(reminder->GetBundleName());
479 option.SetUid(reminder->GetUid());
480 uint32_t slotFlags;
481 ErrCode err = NotificationHelper::GetNotificationSlotFlagsAsBundle(option, slotFlags);
482 if (err != ERR_OK) {
483 ANSR_LOGE("GetNotificationSlotFlagsAsBundle failed.");
484 return false;
485 }
486 if (!(slotFlags & 1)) {
487 return false;
488 }
489 std::string uriStr = USER_SETINGS_DATA_SECURE_URI + std::to_string(reminder->GetUserId())
490 + FOCUS_MODE_ENABLE_URI;
491 Uri enableUri(uriStr);
492 std::string enable;
493 bool ret = ReminderDataShareHelper::GetInstance().Query(enableUri, FOCUS_MODE_ENABLE, enable);
494 if (!ret) {
495 ANSR_LOGE("Query focus mode enable failed.");
496 return false;
497 }
498 if (enable.compare("1") == 0) {
499 ANSR_LOGI("Currently not is do not disurb mode.");
500 return false;
501 }
502 #endif
503 return true;
504 }
505
ConvertRingChannel(ReminderRequest::RingChannel channel)506 int32_t ReminderDataManager::ConvertRingChannel(ReminderRequest::RingChannel channel)
507 {
508 switch (channel) {
509 case ReminderRequest::RingChannel::ALARM:
510 return static_cast<int32_t>(AudioStandard::StreamUsage::STREAM_USAGE_ALARM);
511 case ReminderRequest::RingChannel::MEDIA:
512 return static_cast<int32_t>(AudioStandard::StreamUsage::STREAM_USAGE_MEDIA);
513 case ReminderRequest::RingChannel::NOTIFICATION:
514 return static_cast<int32_t>(AudioStandard::StreamUsage::STREAM_USAGE_NOTIFICATION);
515 default:
516 return static_cast<int32_t>(AudioStandard::StreamUsage::STREAM_USAGE_ALARM);
517 }
518 }
519 }
520 }
521