blob: 36ac5d5a111d3d3fb083f0c68e1e5906c646672e [file] [log] [blame]
Julia Reynolds924eed12017-01-19 09:52:07 -05001/*
2 * Copyright (C) 2017 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 */
16package com.android.server.notification;
17
Chris Wren89aa2262017-05-05 18:05:56 -040018import static android.app.NotificationManager.IMPORTANCE_HIGH;
19import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050020import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
21import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
Chris Wren89aa2262017-05-05 18:05:56 -040022
Brett Chabot84151d92019-02-27 15:37:59 -080023import static junit.framework.Assert.assertFalse;
24import static junit.framework.Assert.assertTrue;
25
26import static org.mockito.Mockito.when;
27
Julia Reynolds924eed12017-01-19 09:52:07 -050028import android.app.ActivityManager;
29import android.app.Notification;
30import android.app.Notification.Builder;
31import android.app.NotificationChannel;
Lyn Han43fbcbd2020-06-03 17:43:30 -070032import android.app.PendingIntent;
33import android.content.Intent;
34import android.graphics.drawable.Icon;
Robert Snoebergerdaf50b52020-06-18 21:40:30 -040035import android.media.session.MediaSession;
Julia Reynolds924eed12017-01-19 09:52:07 -050036import android.os.UserHandle;
37import android.service.notification.StatusBarNotification;
Julia Reynolds924eed12017-01-19 09:52:07 -050038import android.test.suitebuilder.annotation.SmallTest;
39
Brett Chabot84151d92019-02-27 15:37:59 -080040import androidx.test.runner.AndroidJUnit4;
41
Jason Monk74f5e362017-12-06 08:56:33 -050042import com.android.server.UiServiceTestCase;
43
Julia Reynolds924eed12017-01-19 09:52:07 -050044import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
47import org.mockito.Mock;
48import org.mockito.MockitoAnnotations;
49
50@SmallTest
51@RunWith(AndroidJUnit4.class)
Jason Monk74f5e362017-12-06 08:56:33 -050052public class BadgeExtractorTest extends UiServiceTestCase {
Julia Reynolds924eed12017-01-19 09:52:07 -050053
54 @Mock RankingConfig mConfig;
55
56 private String mPkg = "com.android.server.notification";
57 private int mId = 1001;
58 private String mTag = null;
59 private int mUid = 1000;
60 private int mPid = 2000;
61 private UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
62
63 @Before
64 public void setUp() {
65 MockitoAnnotations.initMocks(this);
66 }
67
Chris Wren89aa2262017-05-05 18:05:56 -040068 private NotificationRecord getNotificationRecord(boolean showBadge, int importanceHigh) {
69 NotificationChannel channel = new NotificationChannel("a", "a", importanceHigh);
70 channel.setShowBadge(showBadge);
71 when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
72
Julia Reynolds924eed12017-01-19 09:52:07 -050073 final Builder builder = new Builder(getContext())
74 .setContentTitle("foo")
75 .setSmallIcon(android.R.drawable.sym_def_app_icon)
76 .setPriority(Notification.PRIORITY_HIGH)
77 .setDefaults(Notification.DEFAULT_SOUND);
78
79 Notification n = builder.build();
80 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
81 mPid, n, mUser, null, System.currentTimeMillis());
Geoffrey Pitscha22f6442017-05-05 16:47:38 +000082 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
Julia Reynolds924eed12017-01-19 09:52:07 -050083 return r;
84 }
85
Lyn Han43fbcbd2020-06-03 17:43:30 -070086 private NotificationRecord getNotificationRecordWithBubble(boolean suppressNotif) {
87 NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_UNSPECIFIED);
88 channel.setShowBadge(/* showBadge */ true);
89 when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
90
91 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
92 PendingIntent.getActivity(mContext, 0, new Intent(), 0),
93 Icon.createWithResource("", 0)).build();
94
95 int flags = metadata.getFlags();
96 if (suppressNotif) {
97 flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
98 } else {
99 flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
100 }
101 metadata.setFlags(flags);
102
103 final Builder builder = new Builder(getContext())
104 .setContentTitle("foo")
105 .setSmallIcon(android.R.drawable.sym_def_app_icon)
106 .setPriority(Notification.PRIORITY_HIGH)
107 .setDefaults(Notification.DEFAULT_SOUND)
108 .setBubbleMetadata(metadata);
109
110 Notification n = builder.build();
111 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
112 mPid, n, mUser, null, System.currentTimeMillis());
113 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
114 return r;
115 }
116
Robert Snoebergerdaf50b52020-06-18 21:40:30 -0400117 private NotificationRecord getNotificationRecordWithMedia(boolean excludeSession) {
118 NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_UNSPECIFIED);
119 channel.setShowBadge(/* showBadge */ true);
120 when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
121
122 Notification.MediaStyle style = new Notification.MediaStyle();
123 if (!excludeSession) {
124 MediaSession session = new MediaSession(getContext(), "BadgeExtractorTestSession");
125 style.setMediaSession(session.getSessionToken());
126 }
127
128 final Builder builder = new Builder(getContext())
129 .setContentTitle("foo")
130 .setSmallIcon(android.R.drawable.sym_def_app_icon)
131 .setPriority(Notification.PRIORITY_HIGH)
132 .setDefaults(Notification.DEFAULT_SOUND)
133 .setStyle(style);
134
135 Notification n = builder.build();
136 StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
137 mPid, n, mUser, null, System.currentTimeMillis());
138 NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
139 return r;
140 }
141
Julia Reynolds924eed12017-01-19 09:52:07 -0500142 //
143 // Tests
144 //
145
146 @Test
147 public void testAppYesChannelNo() throws Exception {
148 BadgeExtractor extractor = new BadgeExtractor();
149 extractor.setConfig(mConfig);
150
Chris Wren89aa2262017-05-05 18:05:56 -0400151 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
Julia Reynolds924eed12017-01-19 09:52:07 -0500152 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
Chris Wren89aa2262017-05-05 18:05:56 -0400153 NotificationRecord r = getNotificationRecord(false, IMPORTANCE_UNSPECIFIED);
Julia Reynolds924eed12017-01-19 09:52:07 -0500154
155 extractor.process(r);
156
157 assertFalse(r.canShowBadge());
158 }
159
160 @Test
161 public void testAppNoChannelYes() throws Exception {
162 BadgeExtractor extractor = new BadgeExtractor();
163 extractor.setConfig(mConfig);
164
Chris Wren89aa2262017-05-05 18:05:56 -0400165 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
Julia Reynolds924eed12017-01-19 09:52:07 -0500166 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(false);
Chris Wren89aa2262017-05-05 18:05:56 -0400167 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_HIGH);
Julia Reynolds924eed12017-01-19 09:52:07 -0500168
169 extractor.process(r);
170
171 assertFalse(r.canShowBadge());
172 }
173
174 @Test
175 public void testAppYesChannelYes() throws Exception {
176 BadgeExtractor extractor = new BadgeExtractor();
177 extractor.setConfig(mConfig);
178
Chris Wren89aa2262017-05-05 18:05:56 -0400179 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
Julia Reynolds924eed12017-01-19 09:52:07 -0500180 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
Chris Wren89aa2262017-05-05 18:05:56 -0400181 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
Julia Reynolds924eed12017-01-19 09:52:07 -0500182
183 extractor.process(r);
184
185 assertTrue(r.canShowBadge());
186 }
187
188 @Test
189 public void testAppNoChannelNo() throws Exception {
190 BadgeExtractor extractor = new BadgeExtractor();
191 extractor.setConfig(mConfig);
192
Chris Wren89aa2262017-05-05 18:05:56 -0400193 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
Julia Reynolds924eed12017-01-19 09:52:07 -0500194 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(false);
Chris Wren89aa2262017-05-05 18:05:56 -0400195 NotificationRecord r = getNotificationRecord(false, IMPORTANCE_UNSPECIFIED);
Julia Reynolds924eed12017-01-19 09:52:07 -0500196
Chris Wren89aa2262017-05-05 18:05:56 -0400197 extractor.process(r);
198
199 assertFalse(r.canShowBadge());
200 }
201
202 @Test
203 public void testAppYesChannelYesUserNo() throws Exception {
204 BadgeExtractor extractor = new BadgeExtractor();
205 extractor.setConfig(mConfig);
206
207 when(mConfig.badgingEnabled(mUser)).thenReturn(false);
208 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
209 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_HIGH);
Julia Reynolds924eed12017-01-19 09:52:07 -0500210
211 extractor.process(r);
212
213 assertFalse(r.canShowBadge());
214 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500215
216 @Test
Lyn Han43fbcbd2020-06-03 17:43:30 -0700217 public void testHideNotifOverridesYes() throws Exception {
218 BadgeExtractor extractor = new BadgeExtractor();
219 extractor.setConfig(mConfig);
220
221 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
222 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
223 NotificationRecord r = getNotificationRecordWithBubble(/* suppressNotif */ true);
224
225 extractor.process(r);
226
227 assertFalse(r.canShowBadge());
228 }
229
230 @Test
Robert Snoebergerdaf50b52020-06-18 21:40:30 -0400231 public void testHideMediaNotifOverridesYes() throws Exception {
232 BadgeExtractor extractor = new BadgeExtractor();
233 extractor.setConfig(mConfig);
234 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
235 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
236
237 when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(true);
238 NotificationRecord r = getNotificationRecordWithMedia(/* excludeSession */ false);
239
240 extractor.process(r);
241
242 assertFalse(r.canShowBadge());
243 }
244
245 @Test
246 public void testHideMediaNotifDisabledOverridesNo() throws Exception {
247 BadgeExtractor extractor = new BadgeExtractor();
248 extractor.setConfig(mConfig);
249 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
250 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
251
252 when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(false);
253 NotificationRecord r = getNotificationRecordWithMedia(/* excludeSession */ false);
254
255 extractor.process(r);
256
257 assertTrue(r.canShowBadge());
258 }
259
260 @Test
261 public void testHideMediaNotifNoSessionOverridesNo() throws Exception {
262 BadgeExtractor extractor = new BadgeExtractor();
263 extractor.setConfig(mConfig);
264 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
265 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
266
267 when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(true);
268 NotificationRecord r = getNotificationRecordWithMedia(/* excludeSession */ true);
269
270 extractor.process(r);
271
272 assertTrue(r.canShowBadge());
273 }
274
275 @Test
276 public void testHideMediaNotifNotMediaStyleOverridesNo() throws Exception {
277 BadgeExtractor extractor = new BadgeExtractor();
278 extractor.setConfig(mConfig);
279 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
280 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
281
282 when(mConfig.isMediaNotificationFilteringEnabled()).thenReturn(true);
283 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
284
285 extractor.process(r);
286
287 assertTrue(r.canShowBadge());
288 }
289
290 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500291 public void testDndOverridesYes() {
292 BadgeExtractor extractor = new BadgeExtractor();
293 extractor.setConfig(mConfig);
294
295 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
296 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
297 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
298 r.setIntercepted(true);
299 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
300
301 extractor.process(r);
302
303 assertFalse(r.canShowBadge());
304 }
305
306 @Test
307 public void testDndOConsidersInterception() {
308 BadgeExtractor extractor = new BadgeExtractor();
309 extractor.setConfig(mConfig);
310
311 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
312 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
313 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
314 r.setIntercepted(false);
315 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
316
317 extractor.process(r);
318
319 assertTrue(r.canShowBadge());
320 }
321
322 @Test
323 public void testDndConsidersSuppressedVisualEffects() {
324 BadgeExtractor extractor = new BadgeExtractor();
325 extractor.setConfig(mConfig);
326
327 when(mConfig.badgingEnabled(mUser)).thenReturn(true);
328 when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
329 NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
330 r.setIntercepted(true);
331 r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
332
333 extractor.process(r);
334
335 assertTrue(r.canShowBadge());
336 }
Julia Reynolds924eed12017-01-19 09:52:07 -0500337}