1 /*
2 * Copyright (c) 2021-2023 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 <functional>
19 #include <iomanip>
20 #include <sstream>
21
22 #include "access_token_helper.h"
23 #include "ans_inner_errors.h"
24 #include "ans_log_wrapper.h"
25 #include "ans_permission_def.h"
26 #include "errors.h"
27 #include "common_event_manager.h"
28 #include "common_event_support.h"
29 #include "hitrace_meter_adapter.h"
30 #include "ipc_skeleton.h"
31
32 #include "advanced_notification_inline.cpp"
33
34 namespace OHOS {
35 namespace Notification {
AddSlots(const std::vector<sptr<NotificationSlot>> & slots)36 ErrCode AdvancedNotificationService::AddSlots(const std::vector<sptr<NotificationSlot>> &slots)
37 {
38 ANS_LOGD("%{public}s", __FUNCTION__);
39
40 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
41 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
42 return ERR_ANS_NON_SYSTEM_APP;
43 }
44
45 if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
46 return ERR_ANS_PERMISSION_DENIED;
47 }
48
49 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
50 if (bundleOption == nullptr) {
51 return ERR_ANS_INVALID_BUNDLE;
52 }
53
54 if (slots.size() == 0) {
55 return ERR_ANS_INVALID_PARAM;
56 }
57
58 if (notificationSvrQueue_ == nullptr) {
59 ANS_LOGE("Serial queue is invalid.");
60 return ERR_ANS_INVALID_PARAM;
61 }
62 ErrCode result = ERR_OK;
63 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
64 ANS_LOGD("ffrt enter!");
65 std::vector<sptr<NotificationSlot>> addSlots;
66 for (auto slot : slots) {
67 sptr<NotificationSlot> originalSlot;
68 result =
69 NotificationPreferences::GetInstance().GetNotificationSlot(bundleOption, slot->GetType(), originalSlot);
70 if ((result == ERR_OK) && (originalSlot != nullptr)) {
71 continue;
72 } else {
73 addSlots.push_back(slot);
74 }
75 }
76
77 if (addSlots.size() == 0) {
78 result = ERR_OK;
79 } else {
80 result = NotificationPreferences::GetInstance().AddNotificationSlots(bundleOption, addSlots);
81 }
82 }));
83 notificationSvrQueue_->wait(handler);
84 return result;
85 }
86
GetSlots(std::vector<sptr<NotificationSlot>> & slots)87 ErrCode AdvancedNotificationService::GetSlots(std::vector<sptr<NotificationSlot>> &slots)
88 {
89 ANS_LOGD("%{public}s", __FUNCTION__);
90
91 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
92 if (bundleOption == nullptr) {
93 return ERR_ANS_INVALID_BUNDLE;
94 }
95
96 if (notificationSvrQueue_ == nullptr) {
97 ANS_LOGE("NotificationSvrQueue_ is nullptr.");
98 return ERR_ANS_INVALID_PARAM;
99 }
100 ErrCode result = ERR_OK;
101 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
102 ANS_LOGD("ffrt enter!");
103 result = NotificationPreferences::GetInstance().GetNotificationAllSlots(bundleOption, slots);
104 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
105 result = ERR_OK;
106 slots.clear();
107 }
108 }));
109 notificationSvrQueue_->wait(handler);
110 return result;
111 }
112
GetSlotsByBundle(const sptr<NotificationBundleOption> & bundleOption,std::vector<sptr<NotificationSlot>> & slots)113 ErrCode AdvancedNotificationService::GetSlotsByBundle(
114 const sptr<NotificationBundleOption> &bundleOption, std::vector<sptr<NotificationSlot>> &slots)
115 {
116 ANS_LOGD("%{public}s", __FUNCTION__);
117
118 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
119 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
120 ANS_LOGD("IsSystemApp is false.");
121 return ERR_ANS_NON_SYSTEM_APP;
122 }
123
124 if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
125 return ERR_ANS_PERMISSION_DENIED;
126 }
127
128 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
129 if (bundle == nullptr) {
130 ANS_LOGD("GenerateValidBundleOption failed.");
131 return ERR_ANS_INVALID_BUNDLE;
132 }
133
134 if (notificationSvrQueue_ == nullptr) {
135 ANS_LOGE("Serial queue is invalid.");
136 return ERR_ANS_INVALID_PARAM;
137 }
138 ErrCode result = ERR_OK;
139 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
140 ANS_LOGD("ffrt enter!");
141 result = NotificationPreferences::GetInstance().GetNotificationAllSlots(bundle, slots);
142 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
143 result = ERR_OK;
144 slots.clear();
145 }
146 }));
147
148 notificationSvrQueue_->wait(handler);
149 return result;
150 }
151
UpdateSlots(const sptr<NotificationBundleOption> & bundleOption,const std::vector<sptr<NotificationSlot>> & slots)152 ErrCode AdvancedNotificationService::UpdateSlots(
153 const sptr<NotificationBundleOption> &bundleOption, const std::vector<sptr<NotificationSlot>> &slots)
154 {
155 ANS_LOGD("%{public}s", __FUNCTION__);
156
157 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
158 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
159 return ERR_ANS_NON_SYSTEM_APP;
160 }
161
162 if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
163 ANS_LOGD("CheckPermission is false.");
164 return ERR_ANS_PERMISSION_DENIED;
165 }
166
167 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
168 if (bundle == nullptr) {
169 return ERR_ANS_INVALID_BUNDLE;
170 }
171
172 if (notificationSvrQueue_ == nullptr) {
173 ANS_LOGE("notificationSvrQueue_ is nullptr.");
174 return ERR_ANS_INVALID_PARAM;
175 }
176 ErrCode result = ERR_OK;
177 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
178 ANS_LOGD("ffrt enter!");
179 result = NotificationPreferences::GetInstance().UpdateNotificationSlots(bundle, slots);
180 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
181 result = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST;
182 }
183 }));
184 notificationSvrQueue_->wait(handler);
185
186 if (result == ERR_OK) {
187 PublishSlotChangeCommonEvent(bundle);
188 }
189
190 return result;
191 }
192
RemoveAllSlots()193 ErrCode AdvancedNotificationService::RemoveAllSlots()
194 {
195 ANS_LOGD("%{public}s", __FUNCTION__);
196
197 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
198 if (bundleOption == nullptr) {
199 ANS_LOGD("GenerateBundleOption defeat.");
200 return ERR_ANS_INVALID_BUNDLE;
201 }
202
203 if (notificationSvrQueue_ == nullptr) {
204 ANS_LOGE("Serial queue is invalid.");
205 return ERR_ANS_INVALID_PARAM;
206 }
207 ErrCode result = ERR_OK;
208 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
209 ANS_LOGD("ffrt enter!");
210 sptr<NotificationSlot> liveViewSlot;
211
212 bool isLiveViewSlotExist = true;
213 // retain liveview slot before removeNotificationAllSlots
214 if (NotificationPreferences::GetInstance().GetNotificationSlot(
215 bundleOption, NotificationConstant::SlotType::LIVE_VIEW, liveViewSlot) != ERR_OK) {
216 isLiveViewSlotExist = false;
217 }
218
219 result = NotificationPreferences::GetInstance().RemoveNotificationAllSlots(bundleOption);
220 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
221 result = ERR_OK;
222 }
223
224 if (!isLiveViewSlotExist) {
225 return;
226 }
227 // retain liveview slot when caller is not sa or systemapp
228 if ((result == ERR_OK) &&
229 (IsAllowedRemoveSlot(bundleOption, NotificationConstant::SlotType::LIVE_VIEW) != ERR_OK)) {
230 std::vector<sptr<NotificationSlot>> slots;
231
232 slots.push_back(liveViewSlot);
233 (void)NotificationPreferences::GetInstance().AddNotificationSlots(bundleOption, slots);
234 }
235 }));
236 notificationSvrQueue_->wait(handler);
237 return result;
238 }
239
AddSlotByType(NotificationConstant::SlotType slotType)240 ErrCode AdvancedNotificationService::AddSlotByType(NotificationConstant::SlotType slotType)
241 {
242 ANS_LOGD("%{public}s", __FUNCTION__);
243
244 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
245 if (bundleOption == nullptr) {
246 return ERR_ANS_INVALID_BUNDLE;
247 }
248
249 if (notificationSvrQueue_ == nullptr) {
250 ANS_LOGE("Serial queue is invalidity.");
251 return ERR_ANS_INVALID_PARAM;
252 }
253 ErrCode result = ERR_OK;
254 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
255 ANS_LOGD("ffrt enter!");
256 sptr<NotificationSlot> slot;
257 result = NotificationPreferences::GetInstance().GetNotificationSlot(bundleOption, slotType, slot);
258 if ((result == ERR_OK) && (slot != nullptr)) {
259 return;
260 } else {
261 slot = new (std::nothrow) NotificationSlot(slotType);
262 if (slot == nullptr) {
263 ANS_LOGE("Failed to create NotificationSlot instance");
264 return;
265 }
266
267 std::vector<sptr<NotificationSlot>> slots;
268 slots.push_back(slot);
269 result = NotificationPreferences::GetInstance().AddNotificationSlots(bundleOption, slots);
270 }
271 }));
272 notificationSvrQueue_->wait(handler);
273 return result;
274 }
275
GetEnabledForBundleSlotSelf(const NotificationConstant::SlotType & slotType,bool & enabled)276 ErrCode AdvancedNotificationService::GetEnabledForBundleSlotSelf(
277 const NotificationConstant::SlotType &slotType, bool &enabled)
278 {
279 ANS_LOGD("slotType: %{public}d", slotType);
280
281 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
282 if (bundleOption == nullptr) {
283 return ERR_ANS_INVALID_BUNDLE;
284 }
285
286 if (notificationSvrQueue_ == nullptr) {
287 ANS_LOGE("Serial queue is invalid.");
288 return ERR_ANS_INVALID_PARAM;
289 }
290 ErrCode result = ERR_OK;
291 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
292 ANS_LOGD("ffrt enter!");
293 sptr<NotificationSlot> slot;
294 result = NotificationPreferences::GetInstance().GetNotificationSlot(bundleOption, slotType, slot);
295 if (result != ERR_OK) {
296 ANS_LOGE("Get enable slot self: GetNotificationSlot failed");
297 return;
298 }
299 if (slot == nullptr) {
300 ANS_LOGW("Get enable slot: object is null, enabled default true");
301 enabled = true;
302 result = ERR_OK;
303 return;
304 }
305 enabled = slot->GetEnable();
306 }));
307 notificationSvrQueue_->wait(handler);
308
309 return result;
310 }
311
GetSlotFlagsAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint32_t & slotFlags)312 ErrCode AdvancedNotificationService::GetSlotFlagsAsBundle(const sptr<NotificationBundleOption> &bundleOption,
313 uint32_t &slotFlags)
314 {
315 ANS_LOGD("%{public}s", __FUNCTION__);
316
317 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
318 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
319 return ERR_ANS_NON_SYSTEM_APP;
320 }
321
322 if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
323 return ERR_ANS_PERMISSION_DENIED;
324 }
325
326 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
327 if (bundle == nullptr) {
328 ANS_LOGD("Bundle is null.");
329 return ERR_ANS_INVALID_BUNDLE;
330 }
331
332 if (notificationSvrQueue_ == nullptr) {
333 ANS_LOGE("Serial queue is invalid.");
334 return ERR_ANS_INVALID_PARAM;
335 }
336 ErrCode result = ERR_OK;
337 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
338 ANS_LOGD("ffrt enter!");
339 result = NotificationPreferences::GetInstance().GetNotificationSlotFlagsForBundle(bundle, slotFlags);
340 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
341 result = ERR_OK;
342 slotFlags = 0;
343 }
344 }));
345 notificationSvrQueue_->wait(handler);
346
347 return result;
348 }
349
SetSlotFlagsAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint32_t slotFlags)350 ErrCode AdvancedNotificationService::SetSlotFlagsAsBundle(const sptr<NotificationBundleOption> &bundleOption,
351 uint32_t slotFlags)
352 {
353 ANS_LOGD("%{public}s", __FUNCTION__);
354 if (bundleOption == nullptr) {
355 ANS_LOGD("BundleOption is null.");
356 return ERR_ANS_INVALID_BUNDLE;
357 }
358
359 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
360 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
361 ANS_LOGD("IsSystemApp is false.");
362 return ERR_ANS_NON_SYSTEM_APP;
363 }
364
365 if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
366 return ERR_ANS_PERMISSION_DENIED;
367 }
368
369 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
370 if (bundle == nullptr) {
371 ANS_LOGD("Bundle is null.");
372 return ERR_ANS_INVALID_BUNDLE;
373 }
374
375 if (notificationSvrQueue_ == nullptr) {
376 ANS_LOGE("Serial queue is invalidity.");
377 return ERR_ANS_INVALID_PARAM;
378 }
379 ErrCode result = ERR_OK;
380 ffrt::task_handle handler = notificationSvrQueue_->submit_h(
381 std::bind([&]() {
382 result = NotificationPreferences::GetInstance().SetNotificationSlotFlagsForBundle(bundle, slotFlags);
383 }));
384 notificationSvrQueue_->wait(handler);
385 return result;
386 }
387
SetRequestBySlotType(const sptr<NotificationRequest> & request)388 void AdvancedNotificationService::SetRequestBySlotType(const sptr<NotificationRequest> &request)
389 {
390 ANS_LOGD("%{public}s", __FUNCTION__);
391 NotificationConstant::SlotType type = request->GetSlotType();
392 auto flags = std::make_shared<NotificationFlags>();
393
394 switch (type) {
395 case NotificationConstant::SlotType::SOCIAL_COMMUNICATION:
396 flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN);
397 flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN);
398 break;
399 case NotificationConstant::SlotType::SERVICE_REMINDER:
400 flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN);
401 flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN);
402 break;
403 case NotificationConstant::SlotType::CONTENT_INFORMATION:
404 flags->SetSoundEnabled(NotificationConstant::FlagStatus::CLOSE);
405 flags->SetVibrationEnabled(NotificationConstant::FlagStatus::CLOSE);
406 break;
407 case NotificationConstant::SlotType::LIVE_VIEW:
408 flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN);
409 flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN);
410 break;
411 case NotificationConstant::SlotType::OTHER:
412 flags->SetSoundEnabled(NotificationConstant::FlagStatus::CLOSE);
413 flags->SetVibrationEnabled(NotificationConstant::FlagStatus::CLOSE);
414 break;
415 case NotificationConstant::SlotType::CUSTOMER_SERVICE:
416 flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN);
417 flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN);
418 break;
419 default:
420 break;
421 }
422 request->SetFlags(flags);
423 }
424
GetSlotByType(const NotificationConstant::SlotType & slotType,sptr<NotificationSlot> & slot)425 ErrCode AdvancedNotificationService::GetSlotByType(
426 const NotificationConstant::SlotType &slotType, sptr<NotificationSlot> &slot)
427 {
428 ANS_LOGD("%{public}s", __FUNCTION__);
429
430 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
431 if (bundleOption == nullptr) {
432 ANS_LOGD("Failed to generateBundleOption.");
433 return ERR_ANS_INVALID_BUNDLE;
434 }
435
436 if (notificationSvrQueue_ == nullptr) {
437 ANS_LOGE("Serial queue is invalid.");
438 return ERR_ANS_INVALID_PARAM;
439 }
440 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
441 ANS_LOGD("ffrt enter!");
442 NotificationPreferences::GetInstance().GetNotificationSlot(bundleOption, slotType, slot);
443 }));
444 notificationSvrQueue_->wait(handler);
445 // if get slot failed, it still return ok.
446 return ERR_OK;
447 }
448
RemoveSlotByType(const NotificationConstant::SlotType & slotType)449 ErrCode AdvancedNotificationService::RemoveSlotByType(const NotificationConstant::SlotType &slotType)
450 {
451 ANS_LOGD("%{public}s", __FUNCTION__);
452
453 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
454 if (bundleOption == nullptr) {
455 return ERR_ANS_INVALID_BUNDLE;
456 }
457
458 if (notificationSvrQueue_ == nullptr) {
459 ANS_LOGE("notificationSvrQueue_ is nullptr.");
460 return ERR_ANS_INVALID_PARAM;
461 }
462
463 ErrCode result = ERR_OK;
464 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
465 ANS_LOGD("ffrt enter!");
466 result = IsAllowedRemoveSlot(bundleOption, slotType);
467 if (result != ERR_OK) {
468 ANS_LOGE("Liveview slot cann't remove.");
469 return;
470 }
471
472 NotificationPreferences::GetInstance().RemoveNotificationSlot(bundleOption, slotType);
473 }));
474 notificationSvrQueue_->wait(handler);
475 // if remove slot failed, it still return ok.
476 return result;
477 }
478
GetSlotNumAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint64_t & num)479 ErrCode AdvancedNotificationService::GetSlotNumAsBundle(
480 const sptr<NotificationBundleOption> &bundleOption, uint64_t &num)
481 {
482 ANS_LOGD("%{public}s", __FUNCTION__);
483
484 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
485 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
486 return ERR_ANS_NON_SYSTEM_APP;
487 }
488
489 if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
490 return ERR_ANS_PERMISSION_DENIED;
491 }
492
493 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
494 if (bundle == nullptr) {
495 ANS_LOGD("Bundle is null.");
496 return ERR_ANS_INVALID_BUNDLE;
497 }
498
499 if (notificationSvrQueue_ == nullptr) {
500 ANS_LOGE("Serial queue is invalid.");
501 return ERR_ANS_INVALID_PARAM;
502 }
503 ErrCode result = ERR_OK;
504 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
505 ANS_LOGD("ffrt enter!");
506 result = NotificationPreferences::GetInstance().GetNotificationSlotsNumForBundle(bundle, num);
507 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
508 result = ERR_OK;
509 num = 0;
510 }
511 }));
512 notificationSvrQueue_->wait(handler);
513
514 return result;
515 }
516
PublishSlotChangeCommonEvent(const sptr<NotificationBundleOption> & bundleOption)517 bool AdvancedNotificationService::PublishSlotChangeCommonEvent(const sptr<NotificationBundleOption> &bundleOption)
518 {
519 if (bundleOption == nullptr) {
520 return false;
521 }
522 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
523 ANS_LOGD("bundle [%{public}s : %{public}d]", bundleOption->GetBundleName().c_str(), bundleOption->GetUid());
524
525 EventFwk::Want want;
526 AppExecFwk::ElementName element;
527 element.SetBundleName(bundleOption->GetBundleName());
528 want.SetElement(element);
529 want.SetParam(AppExecFwk::Constants::UID, bundleOption->GetUid());
530 want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_SLOT_CHANGE);
531 EventFwk::CommonEventData commonData {want};
532 if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData)) {
533 ANS_LOGE("PublishCommonEvent failed");
534 return false;
535 }
536
537 return true;
538 }
539 } // namespace Notification
540 } // namespace OHOS
541