1 /*
2 * Copyright (c) 2021-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 "slot_manager.h"
17
18 #include "advanced_notification_service.h"
19
20 #include <functional>
21 #include <iomanip>
22 #include <sstream>
23
24 #include "access_token_helper.h"
25 #include "ans_inner_errors.h"
26 #include "ans_log_wrapper.h"
27 #include "ans_permission_def.h"
28 #include "errors.h"
29 #include "common_event_manager.h"
30 #include "common_event_support.h"
31 #include "hitrace_meter_adapter.h"
32 #include "os_account_manager_helper.h"
33 #include "ipc_skeleton.h"
34 #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED
35 #include "smart_reminder_center.h"
36 #endif
37
38 #include "../advanced_notification_inline.cpp"
39 #include "notification_extension_wrapper.h"
40 #include "notification_analytics_util.h"
41 #include "event_report.h"
42
43 namespace OHOS {
44 namespace Notification {
SetEnabledForBundleSlot(MessageParcel & data,MessageParcel & reply)45 ErrCode SlotManager::SetEnabledForBundleSlot(MessageParcel &data, MessageParcel &reply)
46 {
47 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
48 sptr<NotificationBundleOption> bundleOption = data.ReadStrongParcelable<NotificationBundleOption>();
49 if (bundleOption == nullptr) {
50 ANS_LOGE("[HandleSetEnabledForBundleSlot] fail: read bundle failed.");
51 return ERR_ANS_PARCELABLE_FAILED;
52 }
53
54 int32_t type = 0;
55 if (!data.ReadInt32(type)) {
56 ANS_LOGE("[HandleSetEnabledForBundleSlot] fail: read slot type failed.");
57 return ERR_ANS_PARCELABLE_FAILED;
58 }
59 NotificationConstant::SlotType slotType = static_cast<NotificationConstant::SlotType>(type);
60
61 bool enabled = false;
62 if (!data.ReadBool(enabled)) {
63 ANS_LOGE("[HandleSetEnabledForBundleSlot] fail: read enabled failed.");
64 return ERR_ANS_PARCELABLE_FAILED;
65 }
66
67 bool isForceControl = false;
68 if (!data.ReadBool(isForceControl)) {
69 ANS_LOGE("[HandleSetEnabledForBundleSlot] fail: read isForceControl failed.");
70 return ERR_ANS_PARCELABLE_FAILED;
71 }
72
73 ANS_LOGD("slotType: %{public}d, enabled: %{public}d, isForceControl: %{public}d",
74 slotType, enabled, isForceControl);
75 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_5, EventBranchId::BRANCH_4);
76 message.Message(bundleOption->GetBundleName() + "_" +std::to_string(bundleOption->GetUid()) +
77 " slotType: " + std::to_string(static_cast<uint32_t>(slotType)) +
78 " enabled: " +std::to_string(enabled) + "isForceControl" + std::to_string(isForceControl));
79
80 ErrCode result = SetEnabledForBundleSlotSyncQue(bundleOption, slotType, enabled, isForceControl);
81 if (!reply.WriteInt32(result)) {
82 ANS_LOGE("[HandleSetEnabledForBundleSlot] fail: write result failed, ErrCode=%{public}d", result);
83 return ERR_ANS_PARCELABLE_FAILED;
84 }
85
86 SendEnableNotificationSlotHiSysEvent(bundleOption, slotType, enabled, result);
87 message.ErrorCode(result);
88 NotificationAnalyticsUtil::ReportModifyEvent(message);
89 ANS_LOGI("%{public}s_%{public}d, SetEnabledForBundleSlot successful.",
90 bundleOption->GetBundleName().c_str(), bundleOption->GetUid());
91 return result;
92 }
93
SetEnabledForBundleSlotSyncQue(const sptr<NotificationBundleOption> & bundleOption,const NotificationConstant::SlotType & slotType,bool enabled,bool isForceControl)94 ErrCode SlotManager::SetEnabledForBundleSlotSyncQue(
95 const sptr<NotificationBundleOption> &bundleOption,
96 const NotificationConstant::SlotType &slotType, bool enabled, bool isForceControl)
97 {
98 sptr<NotificationBundleOption> bundle = AdvancedNotificationService::GenerateValidBundleOption(bundleOption);
99 if (bundle == nullptr) {
100 return ERR_ANS_INVALID_BUNDLE;
101 }
102
103 auto excuteQueue = AdvancedNotificationService::GetInstance()->GetNotificationSvrQueue();
104 if (excuteQueue == nullptr) {
105 ANS_LOGE("Serial queue is invalid.");
106 return ERR_ANS_INVALID_PARAM;
107 }
108 ErrCode result;
109 ffrt::task_handle handler = excuteQueue->submit_h(std::bind([&]() {
110 result = SetEnabledForBundleSlotInner(bundleOption, bundle, slotType, enabled, isForceControl);
111 }));
112 excuteQueue->wait(handler);
113 return result;
114 }
115
SetEnabledForBundleSlotInner(const sptr<NotificationBundleOption> & bundleOption,const sptr<NotificationBundleOption> & bundle,const NotificationConstant::SlotType & slotType,bool enabled,bool isForceControl)116 ErrCode SlotManager::SetEnabledForBundleSlotInner(
117 const sptr<NotificationBundleOption> &bundleOption,
118 const sptr<NotificationBundleOption> &bundle,
119 const NotificationConstant::SlotType &slotType, bool enabled, bool isForceControl)
120 {
121 sptr<NotificationSlot> slot;
122 ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundle, slotType, slot);
123 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST ||
124 result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
125 slot = new (std::nothrow) NotificationSlot(slotType);
126 if (slot == nullptr) {
127 ANS_LOGE("Failed to create NotificationSlot ptr.");
128 return ERR_ANS_NO_MEMORY;
129 }
130 GenerateSlotReminderMode(slot, bundleOption);
131 return AddSlotThenPublishEvent(slot, bundle, enabled, isForceControl);
132 } else if ((result == ERR_OK) && (slot != nullptr)) {
133 if (slot->GetEnable() == enabled && slot->GetForceControl() == isForceControl) {
134 slot->SetAuthorizedStatus(NotificationSlot::AuthorizedStatus::AUTHORIZED);
135 std::vector<sptr<NotificationSlot>> slots;
136 slots.push_back(slot);
137 return NotificationPreferences::GetInstance()->AddNotificationSlots(bundle, slots);
138 }
139 NotificationPreferences::GetInstance()->RemoveNotificationSlot(bundle, slotType);
140 return AddSlotThenPublishEvent(slot, bundle, enabled, isForceControl);
141 }
142 ANS_LOGE("Set enable slot: GetNotificationSlot failed");
143 return result;
144 }
145
SendEnableNotificationSlotHiSysEvent(const sptr<NotificationBundleOption> & bundleOption,const NotificationConstant::SlotType & slotType,bool enabled,ErrCode errCode)146 void SlotManager::SendEnableNotificationSlotHiSysEvent(
147 const sptr<NotificationBundleOption> &bundleOption, const NotificationConstant::SlotType &slotType,
148 bool enabled, ErrCode errCode)
149 {
150 if (bundleOption == nullptr) {
151 return;
152 }
153
154 EventInfo eventInfo;
155 eventInfo.bundleName = bundleOption->GetBundleName();
156 eventInfo.uid = bundleOption->GetUid();
157 eventInfo.slotType = slotType;
158 eventInfo.enable = enabled;
159 if (errCode != ERR_OK) {
160 eventInfo.errCode = errCode;
161 EventReport::SendHiSysEvent(ENABLE_NOTIFICATION_SLOT_ERROR, eventInfo);
162 } else {
163 EventReport::SendHiSysEvent(ENABLE_NOTIFICATION_SLOT, eventInfo);
164 }
165 }
166
AddSlotThenPublishEvent(const sptr<NotificationSlot> & slot,const sptr<NotificationBundleOption> & bundle,bool enabled,bool isForceControl)167 ErrCode SlotManager::AddSlotThenPublishEvent(
168 const sptr<NotificationSlot> &slot,
169 const sptr<NotificationBundleOption> &bundle,
170 bool enabled, bool isForceControl)
171 {
172 bool allowed = false;
173 ErrCode result = NotificationPreferences::GetInstance()->GetNotificationsEnabledForBundle(bundle, allowed);
174 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
175 result = ERR_OK;
176 allowed = AdvancedNotificationService::GetInstance()->CheckApiCompatibility(bundle);
177 AdvancedNotificationService::GetInstance()->SetDefaultNotificationEnabled(bundle, allowed);
178 }
179
180 slot->SetEnable(enabled);
181 slot->SetForceControl(isForceControl);
182 slot->SetAuthorizedStatus(NotificationSlot::AuthorizedStatus::AUTHORIZED);
183 std::vector<sptr<NotificationSlot>> slots;
184 slots.push_back(slot);
185 result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundle, slots);
186 if (result != ERR_OK) {
187 ANS_LOGE("Set enable slot: AddNotificationSlot failed");
188 return result;
189 }
190
191 if (!slot->GetEnable()) {
192 AdvancedNotificationService::GetInstance()->RemoveNotificationBySlot(
193 bundle, slot, NotificationConstant::DISABLE_SLOT_REASON_DELETE);
194 } else {
195 if (!slot->GetForceControl() && !allowed) {
196 AdvancedNotificationService::GetInstance()->RemoveNotificationBySlot(
197 bundle, slot, NotificationConstant::DISABLE_NOTIFICATION_REASON_DELETE);
198 }
199 }
200
201 AdvancedNotificationService::GetInstance()->PublishSlotChangeCommonEvent(bundle);
202 return result;
203 }
204 } // namespace Notification
205 } // namespace OHOS
206