blob: f99662e69b8e22d8c14f64746a55929705954875 [file] [log] [blame]
Gus Prevasec9e1f02018-12-18 15:28:12 -05001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.notification;
18
19import android.Manifest;
20import android.app.AppGlobals;
21import android.app.Notification;
22import android.content.pm.IPackageManager;
23import android.content.pm.PackageManager;
24import android.os.RemoteException;
25import android.service.notification.StatusBarNotification;
26
27import com.android.internal.annotations.VisibleForTesting;
28import com.android.systemui.Dependency;
29import com.android.systemui.ForegroundServiceController;
30import com.android.systemui.statusbar.NotificationLockscreenUserManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050031import com.android.systemui.statusbar.notification.collection.NotificationData;
32import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gus Prevasec9e1f02018-12-18 15:28:12 -050033import com.android.systemui.statusbar.phone.NotificationGroupManager;
34import com.android.systemui.statusbar.phone.ShadeController;
35import com.android.systemui.statusbar.phone.StatusBar;
36
37import javax.inject.Inject;
38import javax.inject.Singleton;
39
40/** Component which manages the various reasons a notification might be filtered out. */
41@Singleton
42public class NotificationFilter {
43
44 private final NotificationGroupManager mGroupManager = Dependency.get(
45 NotificationGroupManager.class);
46
47 private NotificationData.KeyguardEnvironment mEnvironment;
48 private ShadeController mShadeController;
49 private ForegroundServiceController mFsc;
50 private NotificationLockscreenUserManager mUserManager;
51
52 @Inject
53 public NotificationFilter() {}
54
55 private NotificationData.KeyguardEnvironment getEnvironment() {
56 if (mEnvironment == null) {
57 mEnvironment = Dependency.get(NotificationData.KeyguardEnvironment.class);
58 }
59 return mEnvironment;
60 }
61
62 private ShadeController getShadeController() {
63 if (mShadeController == null) {
64 mShadeController = Dependency.get(ShadeController.class);
65 }
66 return mShadeController;
67 }
68
69 private ForegroundServiceController getFsc() {
70 if (mFsc == null) {
71 mFsc = Dependency.get(ForegroundServiceController.class);
72 }
73 return mFsc;
74 }
75
76 private NotificationLockscreenUserManager getUserManager() {
77 if (mUserManager == null) {
78 mUserManager = Dependency.get(NotificationLockscreenUserManager.class);
79 }
80 return mUserManager;
81 }
82
83
84 /**
85 * @return true if the provided notification should NOT be shown right now.
86 */
Ned Burnsf81c4c42019-01-07 14:10:43 -050087 public boolean shouldFilterOut(NotificationEntry entry) {
Gus Prevasec9e1f02018-12-18 15:28:12 -050088 final StatusBarNotification sbn = entry.notification;
89 if (!(getEnvironment().isDeviceProvisioned()
90 || showNotificationEvenIfUnprovisioned(sbn))) {
91 return true;
92 }
93
94 if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
95 return true;
96 }
97
98 if (getUserManager().isLockscreenPublicMode(sbn.getUserId())
99 && (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
100 || getUserManager().shouldHideNotifications(sbn.getUserId())
101 || getUserManager().shouldHideNotifications(sbn.getKey()))) {
102 return true;
103 }
104
105 if (getShadeController().isDozing() && entry.shouldSuppressAmbient()) {
106 return true;
107 }
108
109 if (!getShadeController().isDozing() && entry.shouldSuppressNotificationList()) {
110 return true;
111 }
112
113 if (entry.suspended) {
114 return true;
115 }
116
117 if (!StatusBar.ENABLE_CHILD_NOTIFICATIONS
118 && mGroupManager.isChildInGroupWithSummary(sbn)) {
119 return true;
120 }
121
Gus Prevaseb4e2e12018-12-28 14:57:59 -0500122 if (getFsc().isDisclosureNotification(sbn)
123 && !getFsc().isDisclosureNeededForUser(sbn.getUserId())) {
Gus Prevasec9e1f02018-12-18 15:28:12 -0500124 // this is a foreground-service disclosure for a user that does not need to show one
125 return true;
126 }
127 if (getFsc().isSystemAlertNotification(sbn)) {
128 final String[] apps = sbn.getNotification().extras.getStringArray(
129 Notification.EXTRA_FOREGROUND_APPS);
130 if (apps != null && apps.length >= 1) {
131 if (!getFsc().isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
132 return true;
133 }
134 }
135 }
Gus Prevasec9e1f02018-12-18 15:28:12 -0500136 return false;
137 }
138
139 // Q: What kinds of notifications should show during setup?
140 // A: Almost none! Only things coming from packages with permission
141 // android.permission.NOTIFICATION_DURING_SETUP that also have special "kind" tags marking them
142 // as relevant for setup (see below).
143 private static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
144 return showNotificationEvenIfUnprovisioned(AppGlobals.getPackageManager(), sbn);
145 }
146
147 @VisibleForTesting
148 static boolean showNotificationEvenIfUnprovisioned(IPackageManager packageManager,
149 StatusBarNotification sbn) {
150 return checkUidPermission(packageManager, Manifest.permission.NOTIFICATION_DURING_SETUP,
151 sbn.getUid()) == PackageManager.PERMISSION_GRANTED
152 && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
153 }
154
155 private static int checkUidPermission(IPackageManager packageManager, String permission,
156 int uid) {
157 try {
158 return packageManager.checkUidPermission(permission, uid);
159 } catch (RemoteException e) {
160 throw e.rethrowFromSystemServer();
161 }
162 }
163}