• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "advanced_notification_service.h"
17 
18 #include "accesstoken_kit.h"
19 #include "access_token_helper.h"
20 #include "advanced_notification_flow_control_service.h"
21 #include "advanced_notification_inline.h"
22 #include "ans_const_define.h"
23 #include "ans_inner_errors.h"
24 #include "ans_log_wrapper.h"
25 #include "ans_trace_wrapper.h"
26 #include "ans_status.h"
27 
28 #include "notification_analytics_util.h"
29 #include "os_account_manager.h"
30 #include "os_account_manager_helper.h"
31 #include "string_wrapper.h"
32 #include "hitrace_util.h"
33 
34 namespace OHOS {
35 namespace Notification {
36 
37 constexpr char FOUNDATION_BUNDLE_NAME[] = "ohos.global.systemres";
38 constexpr int32_t RESSCHED_UID = 1096;
39 constexpr int32_t OPERATION_TYPE_COMMON_EVENT = 4;
40 constexpr int32_t TYPE_CODE_DOWNLOAD = 8;
41 
PublishWithMaxCapacity(const std::string & label,const sptr<NotificationRequest> & request)42 ErrCode AdvancedNotificationService::PublishWithMaxCapacity(
43     const std::string& label, const sptr<NotificationRequest>& request)
44 {
45     return Publish(label, request);
46 }
47 
Publish(const std::string & label,const sptr<NotificationRequest> & request)48 ErrCode AdvancedNotificationService::Publish(const std::string &label, const sptr<NotificationRequest> &request)
49 {
50     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
51     TraceChainUtil traceChain = TraceChainUtil();
52     OHOS::HiviewDFX::HiTraceId traceId = OHOS::HiviewDFX::HiTraceChain::GetId();
53     ANS_LOGD("called");
54 
55     auto fullTokenID = IPCSkeleton::GetCallingFullTokenID();
56     if (Security::AccessToken::AccessTokenKit::IsAtomicServiceByFullTokenID(fullTokenID)) {
57         ANS_LOGE("AtomicService is not allowed to publish notification");
58         return ERR_ANS_PERMISSION_DENIED;
59     }
60 
61     const auto checkResult = CheckNotificationRequest(request);
62     if (checkResult != ERR_OK) {
63         return checkResult;
64     }
65 
66     SetChainIdToExtraInfo(request, traceId);
67     if (request->GetDistributedCollaborate()) {
68         return CollaboratePublish(request);
69     }
70 
71     if (request->IsAtomicServiceNotification()) {
72         return AtomicServicePublish(request);
73     }
74 
75     if (!InitPublishProcess()) {
76         return ERR_ANS_NO_MEMORY;
77     }
78 
79     request->SetCreateTime(GetCurrentTime());
80 
81     bool isUpdateByOwnerAllowed = IsUpdateSystemLiveviewByOwner(request);
82     AnsStatus ansStatus = publishProcess_[request->GetSlotType()]->PublishPreWork(request, isUpdateByOwnerAllowed);
83     if (!ansStatus.Ok()) {
84         ansStatus.AppendSceneBranch(EventSceneId::SCENE_1, EventBranchId::BRANCH_0, "publish prework failed");
85         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, ansStatus.BuildMessage(true));
86         return ansStatus.GetErrCode();
87     }
88 
89     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_1, EventBranchId::BRANCH_1);
90     ErrCode result = CheckUserIdParams(request->GetReceiverUserId());
91     if (result != ERR_OK) {
92         message.SceneId(EventSceneId::SCENE_3).ErrorCode(result).Message("User is invalid", true);
93         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
94         return result;
95     }
96     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
97     request->SetIsSystemApp(AccessTokenHelper::IsSystemApp() || isSubsystem);
98     if (isSubsystem) {
99         return PublishNotificationBySa(request);
100     }
101     CheckRemovalWantAgent(request);
102     do {
103         result = publishProcess_[request->GetSlotType()]->PublishNotificationByApp(request);
104         if (result != ERR_OK) {
105             break;
106         }
107 
108         sptr<NotificationBundleOption> bundleOption;
109         result = PrepareNotificationInfo(request, bundleOption);
110         if (result != ERR_OK) {
111             message.ErrorCode(result).Message("PrepareNotificationInfo failed.");
112             NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
113             break;
114         }
115 
116         result = CheckSoundPermission(request, bundleOption);
117         if (result != ERR_OK) {
118             message.ErrorCode(result).Message("Check sound failed.");
119             NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
120             break;
121         }
122 
123 #ifndef IS_EMULATOR
124         if (IsNeedPushCheck(request)) {
125             result = PushCheck(request);
126         }
127 #endif
128 
129         if (result != ERR_OK) {
130             break;
131         }
132         result = PublishPreparedNotification(request, bundleOption, isUpdateByOwnerAllowed);
133         if (result != ERR_OK) {
134             break;
135         }
136     } while (0);
137 
138     NotificationAnalyticsUtil::ReportAllBundlesSlotEnabled();
139     SendPublishHiSysEvent(request, result);
140     return result;
141 }
142 
SetChainIdToExtraInfo(const sptr<NotificationRequest> & request,OHOS::HiviewDFX::HiTraceId traceId)143 void AdvancedNotificationService::SetChainIdToExtraInfo
144     (const sptr<NotificationRequest> &request, OHOS::HiviewDFX::HiTraceId traceId)
145 {
146     std::shared_ptr<AAFwk::WantParams> additionalData = request->GetAdditionalData();
147     if (!additionalData) {
148         additionalData = std::make_shared<AAFwk::WantParams>();
149     }
150     std::stringstream chainId;
151     chainId << std::hex << traceId.GetChainId();
152     std::string hexTransId;
153     chainId >> std::hex >> hexTransId;
154     additionalData->SetParam("_oh_ans_sys_traceid", AAFwk::String::Box(hexTransId));
155     request->SetAdditionalData(additionalData);
156 }
157 
PublishNotificationForIndirectProxyWithMaxCapacity(const sptr<NotificationRequest> & request)158 ErrCode AdvancedNotificationService::PublishNotificationForIndirectProxyWithMaxCapacity(
159     const sptr<NotificationRequest>& request)
160 {
161     return PublishNotificationForIndirectProxy(request);
162 }
163 
PublishNotificationForIndirectProxy(const sptr<NotificationRequest> & request)164 ErrCode AdvancedNotificationService::PublishNotificationForIndirectProxy(const sptr<NotificationRequest> &request)
165 {
166     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
167     TraceChainUtil traceChain = TraceChainUtil();
168     OHOS::HiviewDFX::HiTraceId traceId = OHOS::HiviewDFX::HiTraceChain::GetId();
169     ANS_LOGD("called");
170 
171     auto fullTokenID = IPCSkeleton::GetCallingFullTokenID();
172     if (Security::AccessToken::AccessTokenKit::IsAtomicServiceByFullTokenID(fullTokenID)) {
173         ANS_LOGE("AtomicService is not allowed to publish notification");
174         return ERR_ANS_PERMISSION_DENIED;
175     }
176 
177     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_9, EventBranchId::BRANCH_0);
178     if (!request) {
179         ANS_LOGE("null request");
180         message.ErrorCode(ERR_ANS_INVALID_PARAM).Message("Request object is nullptr");
181         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
182         return ERR_ANS_INVALID_PARAM;
183     }
184     SetChainIdToExtraInfo(request, traceId);
185     ErrCode result = PrePublishRequest(request);
186     if (result != ERR_OK) {
187         return result;
188     }
189     auto tokenCaller = IPCSkeleton::GetCallingTokenID();
190     bool isSystemApp = AccessTokenHelper::IsSystemApp();
191     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(tokenCaller);
192     if (!isSystemApp  && !isSubsystem && request->GetExtendInfo() != nullptr) {
193         request->SetExtendInfo(nullptr);
194     }
195     bool isAgentController = AccessTokenHelper::VerifyCallerPermission(tokenCaller,
196         OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER);
197     // SA not support sound
198     if (!request->GetSound().empty()) {
199         request->SetSound("");
200     }
201     std::string bundle = request->GetCreatorBundleName();
202     int32_t uid = request->GetCreatorUid();
203     request->SetOwnerUid(uid);
204     request->SetOwnerBundleName(bundle);
205     std::shared_ptr<NotificationRecord> record = std::make_shared<NotificationRecord>();
206     record->request = request;
207     record->isThirdparty = false;
208     record->bundleOption = new (std::nothrow) NotificationBundleOption(bundle, uid);
209     sptr<NotificationBundleOption> bundleOption = new (std::nothrow) NotificationBundleOption(bundle, uid);
210     if (record->bundleOption == nullptr || bundleOption == nullptr) {
211         ANS_LOGE("null bundleOption");
212         message.ErrorCode(ERR_ANS_NO_MEMORY).Message("Failed to create bundleOption");
213         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
214         return ERR_ANS_NO_MEMORY;
215     }
216     record->bundleOption->SetAppInstanceKey(request->GetAppInstanceKey());
217     record->notification = new (std::nothrow) Notification(request);
218     if (record->notification == nullptr) {
219         ANS_LOGE("null notification");
220         message.ErrorCode(ERR_ANS_NO_MEMORY).Message("Failed to create notification");
221         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
222         return ERR_ANS_NO_MEMORY;
223     }
224 
225     if (notificationSvrQueue_ == nullptr) {
226         ANS_LOGE("null notificationSvrQueue");
227         message.ErrorCode(ERR_ANS_NO_MEMORY).Message("Serial queue is invalid.");
228         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
229         return ERR_ANS_INVALID_PARAM;
230     }
231 
232     SetRequestBySlotType(record->request, bundleOption);
233 
234     const int32_t ipcUid = IPCSkeleton::GetCallingUid();
235     ffrt::task_handle handler = notificationSvrQueue_->submit_h([&]() {
236         if (IsDisableNotification(bundle)) {
237             ANS_LOGE("bundle in Disable Notification list, bundleName=%{public}s", bundle.c_str());
238             result = ERR_ANS_REJECTED_WITH_DISABLE_NOTIFICATION;
239             message.BranchId(EventBranchId::BRANCH_1)
240                 .ErrorCode(result).Message("bundle in Disable Notification list, bundleName=" + bundle);
241             return;
242         }
243         if (IsDisableNotificationByKiosk(bundle)) {
244             ANS_LOGE("bundle not in kiosk trust list, bundleName=%{public}s", bundle.c_str());
245             result = ERR_ANS_REJECTED_WITH_DISABLE_NOTIFICATION;
246             return;
247         }
248         if (AssignValidNotificationSlot(record, bundleOption) != ERR_OK) {
249             ANS_LOGE("Can not assign valid slot!");
250         }
251         result = Filter(record);
252         if (result != ERR_OK) {
253             ANS_LOGE("Reject by filters: %{public}d", result);
254             return;
255         }
256 
257         if (!request->IsDoNotDisturbByPassed()) {
258             CheckDoNotDisturbProfile(record);
259         }
260         ChangeNotificationByControlFlags(record, isAgentController);
261         if (IsSaCreateSystemLiveViewAsBundle(record, ipcUid) &&
262         (std::static_pointer_cast<OHOS::Notification::NotificationLocalLiveViewContent>(
263         record->request->GetContent()->GetNotificationContent())->GetType() == TYPE_CODE_DOWNLOAD)) {
264             result = SaPublishSystemLiveViewAsBundle(record);
265             if (result == ERR_OK) {
266                 SendLiveViewUploadHiSysEvent(record, UploadStatus::CREATE);
267             }
268             return;
269         }
270 
271         bool isNotificationExists = IsNotificationExists(record->notification->GetKey());
272         result = FlowControlService::GetInstance().FlowControl(record, ipcUid, isNotificationExists);
273         if (result != ERR_OK) {
274             message.BranchId(EventBranchId::BRANCH_5).ErrorCode(result).Message("publish failed with FlowControl");
275             return;
276         }
277         if (AssignToNotificationList(record) != ERR_OK) {
278             ANS_LOGE("Failed to assign notification list");
279             message.BranchId(EventBranchId::BRANCH_5).ErrorCode(result).Message("Failed to assign notification list");
280             return;
281         }
282 
283         sptr<NotificationSortingMap> sortingMap = GenerateSortingMap();
284         NotificationSubscriberManager::GetInstance()->NotifyConsumed(record->notification, sortingMap);
285         if ((record->request->GetAutoDeletedTime() > GetCurrentTime()) && !record->request->IsCommonLiveView()) {
286             StartAutoDeletedTimer(record);
287         }
288     });
289     notificationSvrQueue_->wait(handler);
290     if (result != ERR_OK) {
291         NotificationAnalyticsUtil::ReportPublishFailedEvent(request, message);
292         return result;
293     }
294     return ERR_OK;
295 }
296 
PublishAsBundle(const sptr<NotificationRequest> & notification,const std::string & representativeBundle)297 ErrCode AdvancedNotificationService::PublishAsBundle(
298     const sptr<NotificationRequest>& notification, const std::string &representativeBundle)
299 {
300     return ERR_INVALID_OPERATION;
301 }
302 
PublishAsBundleWithMaxCapacity(const sptr<NotificationRequest> & notification,const std::string & representativeBundle)303 ErrCode AdvancedNotificationService::PublishAsBundleWithMaxCapacity(
304     const sptr<NotificationRequest>& notification, const std::string &representativeBundle)
305 {
306     return PublishAsBundle(notification, representativeBundle);
307 }
308 
PublishContinuousTaskNotification(const sptr<NotificationRequest> & request)309 ErrCode AdvancedNotificationService::PublishContinuousTaskNotification(const sptr<NotificationRequest> &request)
310 {
311     ANS_LOGD("called");
312 
313     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
314     if (!isSubsystem) {
315         return ERR_ANS_NOT_SYSTEM_SERVICE;
316     }
317 
318     int32_t uid = IPCSkeleton::GetCallingUid();
319     int32_t userId = SUBSCRIBE_USER_INIT;
320     OHOS::AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid, userId);
321     request->SetCreatorUserId(userId);
322     ANS_LOGD("%{public}s, uid=%{public}d userId=%{public}d", __FUNCTION__, uid, userId);
323 
324     if (request->GetCreatorBundleName().empty()) {
325         request->SetCreatorBundleName(FOUNDATION_BUNDLE_NAME);
326     }
327 
328     if (request->GetOwnerBundleName().empty()) {
329         request->SetOwnerBundleName(FOUNDATION_BUNDLE_NAME);
330     }
331 
332     sptr<NotificationBundleOption> bundleOption = nullptr;
333     bundleOption = new (std::nothrow) NotificationBundleOption(std::string(), uid);
334     if (bundleOption == nullptr) {
335         ANS_LOGE("null bundleOption");
336         return ERR_NO_MEMORY;
337     }
338 
339     ErrCode result = PrepareContinuousTaskNotificationRequest(request, uid);
340     if (result != ERR_OK) {
341         return result;
342     }
343     request->SetUnremovable(true);
344     std::shared_ptr<NotificationRecord> record = std::make_shared<NotificationRecord>();
345     record->request = request;
346     record->bundleOption = bundleOption;
347     record->notification = new (std::nothrow) Notification(request);
348     if (record->notification == nullptr) {
349         ANS_LOGE("null notification");
350         return ERR_NO_MEMORY;
351     }
352     record->notification->SetSourceType(NotificationConstant::SourceType::TYPE_CONTINUOUS);
353 
354     if (notificationSvrQueue_ == nullptr) {
355         ANS_LOGE("null notificationSvrQueue");
356         return ERR_ANS_INVALID_PARAM;
357     }
358     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
359         ANS_LOGD("called");
360         if (!IsNotificationExists(record->notification->GetKey())) {
361             AddToNotificationList(record);
362         } else {
363             if (record->request->IsAlertOneTime()) {
364                 CloseAlert(record);
365             }
366             UpdateInNotificationList(record);
367         }
368 
369         UpdateRecentNotification(record->notification, false, 0);
370         sptr<NotificationSortingMap> sortingMap = GenerateSortingMap();
371         NotificationSubscriberManager::GetInstance()->NotifyConsumed(record->notification, sortingMap);
372     }));
373     notificationSvrQueue_->wait(handler);
374 
375     return result;
376 }
377 
UpdateNotificationTimerByUid(const int32_t uid,const bool isPaused)378 ErrCode AdvancedNotificationService::UpdateNotificationTimerByUid(const int32_t uid, const bool isPaused)
379 {
380     bool isSubSystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
381     int32_t callingUid = IPCSkeleton::GetCallingUid();
382     if (!isSubSystem || callingUid != RESSCHED_UID) {
383         ANS_LOGE(" callingUid: %{public}d", callingUid);
384         return ERR_ANS_NOT_SYSTEM_SERVICE;
385     }
386 
387     if (!notificationSvrQueue_) {
388         ANS_LOGE("null notificationSvrQueue");
389         return ERR_ANS_INVALID_PARAM;
390     }
391     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
392         HandleUpdateLiveViewNotificationTimer(uid, isPaused);
393     }));
394     notificationSvrQueue_->wait(handler);
395     return ERR_OK;
396 }
397 
CheckNotificationRequest(const sptr<NotificationRequest> & request)398 ErrCode AdvancedNotificationService::CheckNotificationRequest(const sptr<NotificationRequest> &request)
399 {
400     if (!request) {
401         ANSR_LOGE("null request");
402         return ERR_ANS_INVALID_PARAM;
403     }
404     auto tokenCaller = IPCSkeleton::GetCallingTokenID();
405     bool isSystemApp = AccessTokenHelper::IsSystemApp();
406     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(tokenCaller);
407     bool isAgentController = AccessTokenHelper::VerifyCallerPermission(tokenCaller,
408         OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER);
409 
410     const auto wantAgent = request->GetWantAgent();
411     const auto removalWantAgent = request->GetRemovalWantAgent();
412 
413     auto content = request->GetContent();
414     if (content != nullptr && content->GetContentType() == NotificationContent::Type::MULTILINE) {
415         ErrCode checkCode = CheckNotificationRequestLineWantAgents(content, isAgentController,
416             isSystemApp || isSubsystem);
417         if (checkCode != ERR_OK) {
418             return checkCode;
419         }
420     }
421 
422     const auto isLocalWantAgent = (wantAgent != nullptr && wantAgent->IsLocal()) ||
423         (removalWantAgent != nullptr && removalWantAgent->IsLocal());
424     if (isLocalWantAgent && !(isSystemApp || isSubsystem)) {
425         ANS_LOGE("Local wantAgent does not support non system app");
426         return ERR_ANS_NON_SYSTEM_APP;
427     }
428 
429     if (isLocalWantAgent && !isAgentController) {
430         ANS_LOGE("Local wantAgent does not support permission denied");
431         return ERR_ANS_PERMISSION_DENIED;
432     }
433     if (!isSystemApp  && !isSubsystem && request->GetExtendInfo() != nullptr) {
434         request->SetExtendInfo(nullptr);
435     }
436     return ERR_OK;
437 }
438 
CheckNotificationRequestLineWantAgents(const std::shared_ptr<NotificationContent> & content,bool isAgentController,bool isSystemComp)439 ErrCode AdvancedNotificationService::CheckNotificationRequestLineWantAgents(
440     const std::shared_ptr<NotificationContent> &content, bool isAgentController, bool isSystemComp)
441 {
442     auto multiLineContent =
443         std::static_pointer_cast<NotificationMultiLineContent>(content->GetNotificationContent());
444     if (multiLineContent != nullptr) {
445         auto lineWantAgents = multiLineContent->GetLineWantAgents();
446         if (lineWantAgents.size() > 0) {
447             if (!isSystemComp) {
448                 ANS_LOGE("Local wantAgent does not support non system app");
449                 return ERR_ANS_NON_SYSTEM_APP;
450             }
451             if (!isAgentController) {
452                 ANS_LOGE("LineWantAgents does not support permission denied");
453                 return ERR_ANS_PERMISSION_DENIED;
454             }
455         }
456     }
457     return ERR_OK;
458 }
459 } // Notification
460 } // OHOS