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_status.h"
26
27 #include "hitrace_meter_adapter.h"
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
AtomicServicePublish(const sptr<NotificationRequest> & request)37 ErrCode AdvancedNotificationService::AtomicServicePublish(const sptr<NotificationRequest> &request)
38 {
39 ErrCode result = PermissionVerification();
40 if (result != ERR_OK) {
41 return result;
42 }
43
44 AnsStatus ansStatus = ExecutePublishProcess(request, true);
45 if (!ansStatus.Ok()) {
46 ansStatus.AppendSceneBranch(EventSceneId::SCENE_1, EventBranchId::BRANCH_0, "Execute PublishProcess failed");
47 NotificationAnalyticsUtil::ReportPublishFailedEvent(request, ansStatus.BuildMessage(true));
48 return ansStatus.GetErrCode();
49 }
50
51 sptr<NotificationBundleOption> bundleOption;
52 ansStatus = CheckAndPrepareNotificationInfoWithAtomicService(request, bundleOption);
53 if (!ansStatus.Ok()) {
54 ansStatus.AppendSceneBranch(EventSceneId::SCENE_1, EventBranchId::BRANCH_0,
55 "CheckAndPrepareNotificationInfoWithAtomicService failed");
56 NotificationAnalyticsUtil::ReportPublishFailedEvent(request, ansStatus.BuildMessage(true));
57 SendPublishHiSysEvent(request, result);
58 return ansStatus.GetErrCode();
59 }
60
61 result = PublishPreparedNotification(request, bundleOption, false);
62 if (result != ERR_OK) {
63 SendPublishHiSysEvent(request, result);
64 return result;
65 }
66 return result;
67 }
68
SetCreatorInfoWithAtomicService(const sptr<NotificationRequest> & request)69 ErrCode AdvancedNotificationService::SetCreatorInfoWithAtomicService(const sptr<NotificationRequest> &request)
70 {
71 // set agentBundle
72 std::string agentBundleName = "";
73 if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
74 agentBundleName = GetClientBundleName();
75 if (agentBundleName.empty()) {
76 ANS_LOGE("Failed to GetClientBundleName");
77 return ERR_ANS_INVALID_BUNDLE;
78 }
79 }
80
81 int32_t uid = IPCSkeleton::GetCallingUid();
82 std::shared_ptr<NotificationBundleOption> agentBundle =
83 std::make_shared<NotificationBundleOption>(agentBundleName, uid);
84 if (agentBundle == nullptr) {
85 ANS_LOGE("Failed to create agentBundle instance");
86 return ERR_ANS_INVALID_BUNDLE;
87 }
88 request->SetAgentBundle(agentBundle);
89 int32_t pid = IPCSkeleton::GetCallingPid();
90 request->SetCreatorUid(uid);
91 request->SetCreatorPid(pid);
92 int userId = -1;
93 OsAccountManagerHelper::GetInstance().GetOsAccountLocalIdFromUid(uid, userId);
94 request->SetCreatorUserId(userId);
95 request->SetCreatorBundleName(agentBundleName);
96 return ERR_OK;
97 }
98
CheckAndPrepareNotificationInfoWithAtomicService(const sptr<NotificationRequest> & request,sptr<NotificationBundleOption> & bundleOption)99 AnsStatus AdvancedNotificationService::CheckAndPrepareNotificationInfoWithAtomicService(
100 const sptr<NotificationRequest> &request, sptr<NotificationBundleOption> &bundleOption)
101 {
102 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
103 request->SetIsSystemApp(AccessTokenHelper::IsSystemApp() ||
104 AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()));
105 ErrCode result = CheckUserIdParams(request->GetReceiverUserId());
106 if (result != ERR_OK) {
107 return AnsStatus(result, "User is invalid");
108 }
109 if (request->GetOwnerUserId() <= SUBSCRIBE_USER_INIT || request->GetOwnerBundleName().empty()) {
110 return AnsStatus(ERR_ANS_INVALID_PARAM, "OwnerUserId or OwnerBundleName invalid");
111 }
112 CheckRemovalWantAgent(request);
113 request->SetCreateTime(GetCurrentTime());
114 if (request->GetDeliveryTime() <= 0) {
115 request->SetDeliveryTime(GetCurrentTime());
116 }
117 result = CheckPictureSize(request);
118
119 SetCreatorInfoWithAtomicService(request);
120 request->SetOwnerUid(0);
121
122 FillActionButtons(request);
123
124 bundleOption = new (std::nothrow) NotificationBundleOption(request->GetOwnerBundleName(),
125 request->GetOwnerUid());
126 if (bundleOption == nullptr) {
127 return AnsStatus(ERR_ANS_INVALID_BUNDLE, "create bundleOption failed");
128 }
129 SetClassificationWithVoip(request);
130 request->SetNotDistributed(true);
131 SetRequestBySlotType(request, bundleOption);
132
133 result = CheckSoundPermission(request, bundleOption);
134 if (result != ERR_OK) {
135 return AnsStatus(result, "CheckSoundPermission failed");
136 }
137 if (IsNeedPushCheck(request)) {
138 result = PushCheck(request);
139 if (result != ERR_OK) {
140 return AnsStatus(result, "PushCheck failed");
141 }
142 }
143 return AnsStatus();
144 }
145
ExecutePublishProcess(const sptr<NotificationRequest> & request,bool isUpdateByOwnerAllowed)146 AnsStatus AdvancedNotificationService::ExecutePublishProcess(
147 const sptr<NotificationRequest> &request, bool isUpdateByOwnerAllowed)
148 {
149 if (!InitPublishProcess()) {
150 return AnsStatus(ERR_ANS_NO_MEMORY, "InitPublishProcess failed");
151 }
152
153 AnsStatus ansStatus = publishProcess_[request->GetSlotType()]->PublishPreWork(request, isUpdateByOwnerAllowed);
154 if (!ansStatus.Ok()) {
155 return ansStatus;
156 }
157
158 ErrCode result = publishProcess_[request->GetSlotType()]->PublishNotificationByApp(request);
159 if (result != ERR_OK) {
160 return AnsStatus(result, "PublishNotificationByApp failed");
161 }
162 return AnsStatus();
163 }
164
165 }
166 }