1 /*
2  * Copyright (C) 2016 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 
17 package com.android.server.notification;
18 
19 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
21 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
22 import static android.app.Notification.CATEGORY_CALL;
23 import static android.app.Notification.FLAG_AUTO_CANCEL;
24 import static android.app.Notification.FLAG_BUBBLE;
25 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
26 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
27 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
28 import static android.app.NotificationManager.IMPORTANCE_HIGH;
29 import static android.app.NotificationManager.IMPORTANCE_LOW;
30 import static android.app.NotificationManager.IMPORTANCE_MAX;
31 import static android.app.NotificationManager.IMPORTANCE_NONE;
32 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
33 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
34 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
35 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
36 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
37 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
38 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
39 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
40 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
41 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
42 import static android.content.pm.PackageManager.FEATURE_WATCH;
43 import static android.content.pm.PackageManager.PERMISSION_DENIED;
44 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
45 import static android.os.Build.VERSION_CODES.O_MR1;
46 import static android.os.Build.VERSION_CODES.P;
47 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
48 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
49 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
50 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
51 
52 import static junit.framework.Assert.assertEquals;
53 import static junit.framework.Assert.assertFalse;
54 import static junit.framework.Assert.assertNotNull;
55 import static junit.framework.Assert.assertNull;
56 import static junit.framework.Assert.assertTrue;
57 import static junit.framework.Assert.fail;
58 
59 import static org.mockito.Matchers.anyBoolean;
60 import static org.mockito.Matchers.anyLong;
61 import static org.mockito.Matchers.anyString;
62 import static org.mockito.Matchers.eq;
63 import static org.mockito.Mockito.any;
64 import static org.mockito.Mockito.anyInt;
65 import static org.mockito.Mockito.doAnswer;
66 import static org.mockito.Mockito.doNothing;
67 import static org.mockito.Mockito.mock;
68 import static org.mockito.Mockito.never;
69 import static org.mockito.Mockito.reset;
70 import static org.mockito.Mockito.spy;
71 import static org.mockito.Mockito.timeout;
72 import static org.mockito.Mockito.times;
73 import static org.mockito.Mockito.verify;
74 import static org.mockito.Mockito.when;
75 
76 import android.app.ActivityManager;
77 import android.app.AppOpsManager;
78 import android.app.AutomaticZenRule;
79 import android.app.IActivityManager;
80 import android.app.INotificationManager;
81 import android.app.ITransientNotification;
82 import android.app.IUriGrantsManager;
83 import android.app.Notification;
84 import android.app.Notification.MessagingStyle.Message;
85 import android.app.NotificationChannel;
86 import android.app.NotificationChannelGroup;
87 import android.app.NotificationManager;
88 import android.app.PendingIntent;
89 import android.app.Person;
90 import android.app.RemoteInput;
91 import android.app.admin.DevicePolicyManagerInternal;
92 import android.app.usage.UsageStatsManagerInternal;
93 import android.companion.ICompanionDeviceManager;
94 import android.content.ComponentName;
95 import android.content.ContentUris;
96 import android.content.Context;
97 import android.content.Intent;
98 import android.content.pm.ApplicationInfo;
99 import android.content.pm.IPackageManager;
100 import android.content.pm.PackageManager;
101 import android.content.pm.ParceledListSlice;
102 import android.content.pm.UserInfo;
103 import android.content.res.Resources;
104 import android.graphics.Color;
105 import android.graphics.drawable.Icon;
106 import android.media.AudioManager;
107 import android.net.Uri;
108 import android.os.Binder;
109 import android.os.Build;
110 import android.os.Bundle;
111 import android.os.IBinder;
112 import android.os.Process;
113 import android.os.RemoteException;
114 import android.os.SystemClock;
115 import android.os.UserHandle;
116 import android.os.UserManager;
117 import android.provider.DeviceConfig;
118 import android.provider.MediaStore;
119 import android.provider.Settings;
120 import android.service.notification.Adjustment;
121 import android.service.notification.NotificationListenerService;
122 import android.service.notification.NotificationStats;
123 import android.service.notification.StatusBarNotification;
124 import android.service.notification.ZenPolicy;
125 import android.telephony.TelephonyManager;
126 import android.test.suitebuilder.annotation.SmallTest;
127 import android.testing.AndroidTestingRunner;
128 import android.testing.TestableContext;
129 import android.testing.TestableLooper;
130 import android.testing.TestableLooper.RunWithLooper;
131 import android.testing.TestablePermissions;
132 import android.text.Html;
133 import android.util.ArrayMap;
134 import android.util.ArraySet;
135 import android.util.AtomicFile;
136 
137 import androidx.annotation.Nullable;
138 import androidx.test.InstrumentationRegistry;
139 
140 import com.android.internal.R;
141 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
142 import com.android.internal.statusbar.NotificationVisibility;
143 import com.android.server.LocalServices;
144 import com.android.server.SystemService;
145 import com.android.server.UiServiceTestCase;
146 import com.android.server.lights.LightsManager;
147 import com.android.server.lights.LogicalLight;
148 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
149 import com.android.server.notification.NotificationManagerService.NotificationListeners;
150 import com.android.server.uri.UriGrantsManagerInternal;
151 import com.android.server.wm.WindowManagerInternal;
152 
153 import org.junit.After;
154 import org.junit.Before;
155 import org.junit.Test;
156 import org.junit.runner.RunWith;
157 import org.mockito.ArgumentCaptor;
158 import org.mockito.Mock;
159 import org.mockito.MockitoAnnotations;
160 import org.mockito.stubbing.Answer;
161 
162 import java.io.BufferedInputStream;
163 import java.io.ByteArrayInputStream;
164 import java.io.File;
165 import java.io.FileOutputStream;
166 import java.util.ArrayList;
167 import java.util.Arrays;
168 import java.util.Collections;
169 import java.util.List;
170 import java.util.Map;
171 import java.util.function.Consumer;
172 
173 @SmallTest
174 @RunWith(AndroidTestingRunner.class)
175 @RunWithLooper
176 public class NotificationManagerServiceTest extends UiServiceTestCase {
177     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
178     private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
179             "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
180                     + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
181     private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD =
182             "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
183                     + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
184 
185     private final int mUid = Binder.getCallingUid();
186     private TestableNotificationManagerService mService;
187     private INotificationManager mBinderService;
188     private NotificationManagerInternal mInternalService;
189     @Mock
190     private IPackageManager mPackageManager;
191     @Mock
192     private PackageManager mPackageManagerClient;
193     @Mock
194     private WindowManagerInternal mWindowManagerInternal;
195     private TestableContext mContext = spy(getContext());
196     private final String PKG = mContext.getPackageName();
197     private TestableLooper mTestableLooper;
198     @Mock
199     private RankingHelper mRankingHelper;
200     @Mock private PreferencesHelper mPreferencesHelper;
201     AtomicFile mPolicyFile;
202     File mFile;
203     @Mock
204     private NotificationUsageStats mUsageStats;
205     @Mock
206     private UsageStatsManagerInternal mAppUsageStats;
207     @Mock
208     private AudioManager mAudioManager;
209     @Mock
210     ActivityManager mActivityManager;
211     NotificationManagerService.WorkerHandler mHandler;
212     @Mock
213     Resources mResources;
214 
215     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
216             TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
217 
218     private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
219 
220     @Mock
221     private NotificationListeners mListeners;
222     @Mock private NotificationAssistants mAssistants;
223     @Mock private ConditionProviders mConditionProviders;
224     private ManagedServices.ManagedServiceInfo mListener;
225     @Mock private ICompanionDeviceManager mCompanionMgr;
226     @Mock SnoozeHelper mSnoozeHelper;
227     @Mock GroupHelper mGroupHelper;
228     @Mock
229     IBinder mPermOwner;
230     @Mock
231     IActivityManager mAm;
232     @Mock
233     IUriGrantsManager mUgm;
234     @Mock
235     UriGrantsManagerInternal mUgmInternal;
236     @Mock
237     AppOpsManager mAppOpsManager;
238     @Mock
239     private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
240             mNotificationAssistantAccessGrantedCallback;
241     @Mock
242     UserManager mUm;
243 
244     // Use a Testable subclass so we can simulate calls from the system without failing.
245     private static class TestableNotificationManagerService extends NotificationManagerService {
246         int countSystemChecks = 0;
247         boolean isSystemUid = true;
248         int countLogSmartSuggestionsVisible = 0;
249         @Nullable
250         NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
251 
TestableNotificationManagerService(Context context)252         TestableNotificationManagerService(Context context) {
253             super(context);
254         }
255 
256         @Override
isCallingUidSystem()257         protected boolean isCallingUidSystem() {
258             countSystemChecks++;
259             return isSystemUid;
260         }
261 
262         @Override
isCallerSystemOrPhone()263         protected boolean isCallerSystemOrPhone() {
264             countSystemChecks++;
265             return isSystemUid;
266         }
267 
268         @Override
getCompanionManager()269         protected ICompanionDeviceManager getCompanionManager() {
270             return null;
271         }
272 
273         @Override
reportUserInteraction(NotificationRecord r)274         protected void reportUserInteraction(NotificationRecord r) {
275             return;
276         }
277 
278         @Override
handleSavePolicyFile()279         protected void handleSavePolicyFile() {
280             return;
281         }
282 
283         @Override
logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)284         void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
285             super.logSmartSuggestionsVisible(r, notificationLocation);
286             countLogSmartSuggestionsVisible++;
287         }
288 
289         @Override
setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted)290         protected void setNotificationAssistantAccessGrantedForUserInternal(
291                 ComponentName assistant, int userId, boolean granted) {
292             if (mNotificationAssistantAccessGrantedCallback != null) {
293                 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
294                 return;
295             }
296             super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
297         }
298 
setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)299         private void setNotificationAssistantAccessGrantedCallback(
300                 @Nullable NotificationAssistantAccessGrantedCallback callback) {
301             this.mNotificationAssistantAccessGrantedCallback = callback;
302         }
303 
304         interface NotificationAssistantAccessGrantedCallback {
onGranted(ComponentName assistant, int userId, boolean granted)305             void onGranted(ComponentName assistant, int userId, boolean granted);
306         }
307 
308         @Override
canLaunchInActivityView(Context context, PendingIntent pendingIntent, String packageName)309         protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
310                 String packageName) {
311             // Tests for this not being true are in CTS NotificationManagerTest
312             return true;
313         }
314     }
315 
316     private class TestableToastCallback extends ITransientNotification.Stub {
317         @Override
show(IBinder windowToken)318         public void show(IBinder windowToken) {
319         }
320 
321         @Override
hide()322         public void hide() {
323         }
324     }
325 
326     @Before
setUp()327     public void setUp() throws Exception {
328         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
329                 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
330 
331         MockitoAnnotations.initMocks(this);
332 
333         LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
334         LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
335         LocalServices.removeServiceForTest(WindowManagerInternal.class);
336         LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
337 
338         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
339 
340         mService = new TestableNotificationManagerService(mContext);
341 
342         // Use this testable looper.
343         mTestableLooper = TestableLooper.get(this);
344         mHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
345         // MockPackageManager - default returns ApplicationInfo with matching calling UID
346         mContext.setMockPackageManager(mPackageManagerClient);
347         final ApplicationInfo applicationInfo = new ApplicationInfo();
348         applicationInfo.uid = mUid;
349         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
350                 .thenReturn(applicationInfo);
351         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
352                 .thenReturn(applicationInfo);
353         when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
354         final LightsManager mockLightsManager = mock(LightsManager.class);
355         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
356         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
357         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
358         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
359         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
360         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
361         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
362 
363         // write to a test file; the system file isn't readable from tests
364         mFile = new File(mContext.getCacheDir(), "test.xml");
365         mFile.createNewFile();
366         final String preupgradeXml = "<notification-policy></notification-policy>";
367         mPolicyFile = new AtomicFile(mFile);
368         FileOutputStream fos = mPolicyFile.startWrite();
369         fos.write(preupgradeXml.getBytes());
370         mPolicyFile.finishWrite(fos);
371 
372         // Setup managed services
373         mListener = mListeners.new ManagedServiceInfo(
374                 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
375         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
376         ManagedServices.Config listenerConfig = new ManagedServices.Config();
377         listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
378         when(mListeners.getConfig()).thenReturn(listenerConfig);
379         ManagedServices.Config assistantConfig = new ManagedServices.Config();
380         assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
381         when(mAssistants.getConfig()).thenReturn(assistantConfig);
382         ManagedServices.Config dndConfig = new ManagedServices.Config();
383         dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
384         when(mConditionProviders.getConfig()).thenReturn(dndConfig);
385 
386         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
387 
388 
389         mService.init(mTestableLooper.getLooper(),
390                 mPackageManager, mPackageManagerClient, mockLightsManager,
391                 mListeners, mAssistants, mConditionProviders,
392                 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
393                 mGroupHelper, mAm, mAppUsageStats,
394                 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
395                 mAppOpsManager, mUm, mock(TelephonyManager.class));
396         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
397 
398         mService.setAudioManager(mAudioManager);
399 
400         // Tests call directly into the Binder.
401         mBinderService = mService.getBinderService();
402         mInternalService = mService.getInternalService();
403 
404         mBinderService.createNotificationChannels(
405                 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
406         assertNotNull(mBinderService.getNotificationChannel(
407                 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
408     }
409 
410     @After
tearDown()411     public void tearDown() throws Exception {
412         mFile.delete();
413         clearDeviceConfig();
414         InstrumentationRegistry.getInstrumentation()
415                 .getUiAutomation().dropShellPermissionIdentity();
416     }
417 
waitForIdle()418     public void waitForIdle() {
419         mTestableLooper.processAllMessages();
420     }
421 
setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled, boolean channelEnabled)422     private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
423             boolean channelEnabled) {
424         mService.setPreferencesHelper(mPreferencesHelper);
425         when(mPreferencesHelper.bubblesEnabled()).thenReturn(globalEnabled);
426         when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
427         when(mPreferencesHelper.getNotificationChannel(
428                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
429                 mTestNotificationChannel);
430         when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
431                 mTestNotificationChannel.getImportance());
432         mTestNotificationChannel.setAllowBubbles(channelEnabled);
433     }
434 
generateSbn(String pkg, int uid, long postTime, int userId)435     private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
436         Notification.Builder nb = new Notification.Builder(mContext, "a")
437                 .setContentTitle("foo")
438                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
439         StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0,
440                 nb.build(), new UserHandle(userId), null, postTime);
441         return sbn;
442     }
443 
444 
generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)445     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
446             String groupKey, boolean isSummary) {
447         return generateNotificationRecord(channel, id, groupKey, isSummary, false /* isBubble */);
448     }
449 
generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary, boolean isBubble)450     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
451             String groupKey, boolean isSummary, boolean isBubble) {
452         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
453                 .setContentTitle("foo")
454                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
455                 .setGroup(groupKey)
456                 .setGroupSummary(isSummary);
457         if (isBubble) {
458             nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
459         }
460         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
461                 nb.build(), new UserHandle(mUid), null, 0);
462         return new NotificationRecord(mContext, sbn, channel);
463     }
464 
generateNotificationRecord(NotificationChannel channel)465     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
466         return generateNotificationRecord(channel, null);
467     }
468 
generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)469     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
470             Notification.TvExtender extender) {
471         return generateNotificationRecord(channel, extender, false /* isBubble */);
472     }
473 
generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender, boolean isBubble)474     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
475             Notification.TvExtender extender, boolean isBubble) {
476         if (channel == null) {
477             channel = mTestNotificationChannel;
478         }
479         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
480                 .setContentTitle("foo")
481                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
482         if (extender != null) {
483             nb.extend(extender);
484         }
485         if (isBubble) {
486             nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
487         }
488         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
489                 nb.build(), new UserHandle(mUid), null, 0);
490         return new NotificationRecord(mContext, sbn, channel);
491     }
492 
getSignalExtractorSideEffects()493     private Map<String, Answer> getSignalExtractorSideEffects() {
494         Map<String, Answer> answers = new ArrayMap<>();
495 
496         answers.put("override group key", invocationOnMock -> {
497             ((NotificationRecord) invocationOnMock.getArguments()[0])
498                     .setOverrideGroupKey("bananas");
499             return null;
500         });
501         answers.put("override people", invocationOnMock -> {
502             ((NotificationRecord) invocationOnMock.getArguments()[0])
503                     .setPeopleOverride(new ArrayList<>());
504             return null;
505         });
506         answers.put("snooze criteria", invocationOnMock -> {
507             ((NotificationRecord) invocationOnMock.getArguments()[0])
508                     .setSnoozeCriteria(new ArrayList<>());
509             return null;
510         });
511         answers.put("notification channel", invocationOnMock -> {
512             ((NotificationRecord) invocationOnMock.getArguments()[0])
513                     .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
514             return null;
515         });
516         answers.put("badging", invocationOnMock -> {
517             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
518             r.setShowBadge(!r.canShowBadge());
519             return null;
520         });
521         answers.put("bubbles", invocationOnMock -> {
522             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
523             r.setAllowBubble(!r.canBubble());
524             return null;
525         });
526         answers.put("package visibility", invocationOnMock -> {
527             ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
528                     Notification.VISIBILITY_SECRET);
529             return null;
530         });
531 
532         return answers;
533     }
534 
clearDeviceConfig()535     private void clearDeviceConfig() {
536         DeviceConfig.resetToDefaults(
537                 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
538     }
539 
setDefaultAssistantInDeviceConfig(String componentName)540     private void setDefaultAssistantInDeviceConfig(String componentName) {
541         DeviceConfig.setProperty(
542                 DeviceConfig.NAMESPACE_SYSTEMUI,
543                 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
544                 componentName,
545                 false);
546     }
547 
getBasicBubbleMetadataBuilder()548     private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() {
549         PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
550         return new Notification.BubbleMetadata.Builder()
551                 .setIntent(pi)
552                 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
553     }
554 
addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)555     private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
556             throws RemoteException {
557 
558         // Notification that has bubble metadata
559         NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel, 1,
560                 "BUBBLE_GROUP", false /* isSummary */, true /* isBubble */);
561 
562         // Make the package foreground so that we're allowed to be a bubble
563         when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn(
564                 IMPORTANCE_FOREGROUND);
565 
566         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
567                 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
568         waitForIdle();
569 
570         // Make sure we are a bubble
571         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
572         assertEquals(1, notifsAfter.length);
573         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
574 
575         // Plain notification without bubble metadata
576         NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2,
577                 "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */);
578         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
579                 nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId());
580         waitForIdle();
581 
582         notifsAfter = mBinderService.getActiveNotifications(PKG);
583         assertEquals(2, notifsAfter.length);
584 
585         // Summary notification for both of those
586         NotificationRecord nrSummary = generateNotificationRecord(mTestNotificationChannel, 3,
587                 "BUBBLE_GROUP", true /* isSummary */, false /* isBubble */);
588         if (summaryAutoCancel) {
589             nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
590         }
591         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
592                 nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId());
593         waitForIdle();
594 
595         notifsAfter = mBinderService.getActiveNotifications(PKG);
596         assertEquals(3, notifsAfter.length);
597 
598         return nrSummary;
599     }
600 
601     @Test
testCreateNotificationChannels_SingleChannel()602     public void testCreateNotificationChannels_SingleChannel() throws Exception {
603         final NotificationChannel channel =
604                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
605         mBinderService.createNotificationChannels(PKG,
606                 new ParceledListSlice(Arrays.asList(channel)));
607         final NotificationChannel createdChannel =
608                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
609         assertTrue(createdChannel != null);
610     }
611 
612     @Test
testCreateNotificationChannels_NullChannelThrowsException()613     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
614         try {
615             mBinderService.createNotificationChannels(PKG,
616                     new ParceledListSlice(Arrays.asList((Object[])null)));
617             fail("Exception should be thrown immediately.");
618         } catch (NullPointerException e) {
619             // pass
620         }
621     }
622 
623     @Test
testCreateNotificationChannels_TwoChannels()624     public void testCreateNotificationChannels_TwoChannels() throws Exception {
625         final NotificationChannel channel1 =
626                 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
627         final NotificationChannel channel2 =
628                 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
629         mBinderService.createNotificationChannels(PKG,
630                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
631         assertTrue(mBinderService.getNotificationChannel(
632                 PKG, mContext.getUserId(), PKG, "id1") != null);
633         assertTrue(mBinderService.getNotificationChannel(
634                 PKG, mContext.getUserId(), PKG, "id2") != null);
635     }
636 
637     @Test
testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()638     public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
639             throws Exception {
640         final NotificationChannel channel =
641                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
642         mBinderService.createNotificationChannels(PKG,
643                 new ParceledListSlice(Arrays.asList(channel)));
644 
645         // Recreating the channel doesn't throw, but ignores importance.
646         final NotificationChannel dupeChannel =
647                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
648         mBinderService.createNotificationChannels(PKG,
649                 new ParceledListSlice(Arrays.asList(dupeChannel)));
650         final NotificationChannel createdChannel =
651                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
652         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
653     }
654 
655     @Test
testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()656     public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
657             throws Exception {
658         final NotificationChannel channel =
659                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
660         mBinderService.createNotificationChannels(PKG,
661                 new ParceledListSlice(Arrays.asList(channel)));
662 
663         // Recreating with a lower importance is allowed to modify the channel.
664         final NotificationChannel dupeChannel =
665                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
666         mBinderService.createNotificationChannels(PKG,
667                 new ParceledListSlice(Arrays.asList(dupeChannel)));
668         final NotificationChannel createdChannel =
669                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
670         assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
671     }
672 
673     @Test
testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()674     public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
675             throws Exception {
676         final NotificationChannel channel =
677                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
678         mBinderService.createNotificationChannels(PKG,
679                 new ParceledListSlice(Arrays.asList(channel)));
680 
681         // The user modifies importance directly, can no longer be changed by the app.
682         final NotificationChannel updatedChannel =
683                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
684         mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
685 
686         // Recreating with a lower importance leaves channel unchanged.
687         final NotificationChannel dupeChannel =
688                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
689         mBinderService.createNotificationChannels(PKG,
690                 new ParceledListSlice(Arrays.asList(dupeChannel)));
691         final NotificationChannel createdChannel =
692                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
693         assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
694     }
695 
696     @Test
testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()697     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
698             throws Exception {
699         final NotificationChannel channel1 =
700                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
701         final NotificationChannel channel2 =
702                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
703         mBinderService.createNotificationChannels(PKG,
704                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
705         final NotificationChannel createdChannel =
706                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
707         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
708     }
709 
710     @Test
testBlockedNotifications_suspended()711     public void testBlockedNotifications_suspended() throws Exception {
712         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
713 
714         NotificationChannel channel = new NotificationChannel("id", "name",
715                 IMPORTANCE_HIGH);
716         NotificationRecord r = generateNotificationRecord(channel);
717 
718         // isBlocked is only used for user blocking, not app suspension
719         assertFalse(mService.isBlocked(r, mUsageStats));
720     }
721 
722     @Test
testBlockedNotifications_blockedChannel()723     public void testBlockedNotifications_blockedChannel() throws Exception {
724         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
725 
726         NotificationChannel channel = new NotificationChannel("id", "name",
727                 NotificationManager.IMPORTANCE_NONE);
728         NotificationRecord r = generateNotificationRecord(channel);
729         assertTrue(mService.isBlocked(r, mUsageStats));
730         verify(mUsageStats, times(1)).registerBlocked(eq(r));
731 
732         mBinderService.createNotificationChannels(
733                 PKG, new ParceledListSlice(Arrays.asList(channel)));
734         final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
735         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
736                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
737         waitForIdle();
738         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
739     }
740 
741     @Test
testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()742     public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
743             throws Exception {
744         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
745 
746         NotificationChannel channel = new NotificationChannel("blocked", "name",
747                 NotificationManager.IMPORTANCE_NONE);
748         mBinderService.createNotificationChannels(
749                 PKG, new ParceledListSlice(Arrays.asList(channel)));
750 
751         final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
752         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
753         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
754                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
755         waitForIdle();
756         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
757         assertEquals(IMPORTANCE_LOW,
758                 mService.getNotificationRecord(sbn.getKey()).getImportance());
759         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
760                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
761     }
762 
763     @Test
testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()764     public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
765             throws Exception {
766         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
767 
768         NotificationChannel channel =
769                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
770         mBinderService.createNotificationChannels(
771                 PKG, new ParceledListSlice(Arrays.asList(channel)));
772 
773         NotificationChannel update =
774                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
775         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
776         waitForIdle();
777         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
778                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
779 
780         StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
781         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
782         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
783                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
784         waitForIdle();
785         // The first time a foreground service notification is shown, we allow the channel
786         // to be updated to allow it to be seen.
787         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
788         assertEquals(IMPORTANCE_LOW,
789                 mService.getNotificationRecord(sbn.getKey()).getImportance());
790         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
791                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
792         mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
793         waitForIdle();
794 
795         update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
796         update.setFgServiceShown(true);
797         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
798         waitForIdle();
799         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
800                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
801 
802         sbn = generateNotificationRecord(channel).sbn;
803         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
804         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
805                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
806         waitForIdle();
807         // The second time it is shown, we keep the user's preference.
808         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
809         assertNull(mService.getNotificationRecord(sbn.getKey()));
810         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
811                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
812     }
813 
814     @Test
testBlockedNotifications_blockedChannelGroup()815     public void testBlockedNotifications_blockedChannelGroup() throws Exception {
816         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
817         mService.setPreferencesHelper(mPreferencesHelper);
818         when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true);
819 
820         NotificationChannel channel = new NotificationChannel("id", "name",
821                 NotificationManager.IMPORTANCE_HIGH);
822         channel.setGroup("something");
823         NotificationRecord r = generateNotificationRecord(channel);
824         assertTrue(mService.isBlocked(r, mUsageStats));
825         verify(mUsageStats, times(1)).registerBlocked(eq(r));
826     }
827 
828     @Test
testEnqueuedBlockedNotifications_blockedApp()829     public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
830         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
831 
832         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
833 
834         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
835         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
836                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
837         waitForIdle();
838         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
839     }
840 
841     @Test
testEnqueuedBlockedNotifications_blockedAppForegroundService()842     public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
843         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
844 
845         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
846 
847         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
848         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
849         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
850                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
851         waitForIdle();
852         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
853         assertNull(mService.getNotificationRecord(sbn.getKey()));
854     }
855 
856     /**
857      * Confirm the system user on automotive devices can use car categories
858      */
859     @Test
testEnqueuedRestrictedNotifications_asSystem()860     public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
861         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
862                 .thenReturn(true);
863         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
864                 Notification.CATEGORY_CAR_WARNING,
865                 Notification.CATEGORY_CAR_INFORMATION);
866         int id = 0;
867         for (String category: categories) {
868             final StatusBarNotification sbn =
869                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
870             sbn.getNotification().category = category;
871             mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
872                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
873         }
874         waitForIdle();
875         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
876     }
877 
878 
879     /**
880      * Confirm restricted notification categories only apply to automotive.
881      */
882     @Test
testEnqueuedRestrictedNotifications_notAutomotive()883     public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
884         mService.isSystemUid = false;
885         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
886                 .thenReturn(false);
887         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
888                 Notification.CATEGORY_CAR_WARNING,
889                 Notification.CATEGORY_CAR_INFORMATION);
890         int id = 0;
891         for (String category: categories) {
892             final StatusBarNotification sbn =
893                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
894             sbn.getNotification().category = category;
895             mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
896                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
897         }
898         waitForIdle();
899         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
900     }
901 
902     /**
903      * Confirm if a non-system user tries to use the car categories on a automotive device that
904      * they will get a security exception
905      */
906     @Test
testEnqueuedRestrictedNotifications_badUser()907     public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
908         mService.isSystemUid = false;
909         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
910                 .thenReturn(true);
911         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
912                 Notification.CATEGORY_CAR_WARNING,
913                 Notification.CATEGORY_CAR_INFORMATION);
914         for (String category: categories) {
915             final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
916             sbn.getNotification().category = category;
917             try {
918                 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
919                         sbn.getId(), sbn.getNotification(), sbn.getUserId());
920                 fail("Calls from non system apps should not allow use of restricted categories");
921             } catch (SecurityException e) {
922                 // pass
923             }
924         }
925         waitForIdle();
926         assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
927     }
928 
929     @Test
testBlockedNotifications_blockedByAssistant()930     public void testBlockedNotifications_blockedByAssistant() throws Exception {
931         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
932         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
933 
934         NotificationChannel channel = new NotificationChannel("id", "name",
935                 NotificationManager.IMPORTANCE_HIGH);
936         NotificationRecord r = generateNotificationRecord(channel);
937         mService.addEnqueuedNotification(r);
938 
939         Bundle bundle = new Bundle();
940         bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
941         Adjustment adjustment = new Adjustment(
942                 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
943         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
944 
945         NotificationManagerService.PostNotificationRunnable runnable =
946                 mService.new PostNotificationRunnable(r.getKey());
947         runnable.run();
948         waitForIdle();
949 
950         verify(mUsageStats, never()).registerPostedByApp(any());
951     }
952 
953     @Test
testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()954     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
955         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
956                 generateNotificationRecord(null).getNotification(), 0);
957         waitForIdle();
958         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
959         assertEquals(1, notifs.length);
960         assertEquals(1, mService.getNotificationRecordCount());
961     }
962 
963     @Test
testCancelNotificationImmediatelyAfterEnqueue()964     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
965         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
966                 generateNotificationRecord(null).getNotification(), 0);
967         mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
968         waitForIdle();
969         StatusBarNotification[] notifs =
970                 mBinderService.getActiveNotifications(PKG);
971         assertEquals(0, notifs.length);
972         assertEquals(0, mService.getNotificationRecordCount());
973     }
974 
975     @Test
testCancelNotificationWhilePostedAndEnqueued()976     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
977         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
978                 generateNotificationRecord(null).getNotification(), 0);
979         waitForIdle();
980         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
981                 generateNotificationRecord(null).getNotification(), 0);
982         mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
983         waitForIdle();
984         StatusBarNotification[] notifs =
985                 mBinderService.getActiveNotifications(PKG);
986         assertEquals(0, notifs.length);
987         assertEquals(0, mService.getNotificationRecordCount());
988         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
989         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
990         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
991     }
992 
993     @Test
testCancelNotificationsFromListenerImmediatelyAfterEnqueue()994     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
995         NotificationRecord r = generateNotificationRecord(null);
996         final StatusBarNotification sbn = r.sbn;
997         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
998                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
999         mBinderService.cancelNotificationsFromListener(null, null);
1000         waitForIdle();
1001         StatusBarNotification[] notifs =
1002                 mBinderService.getActiveNotifications(sbn.getPackageName());
1003         assertEquals(0, notifs.length);
1004         assertEquals(0, mService.getNotificationRecordCount());
1005     }
1006 
1007     @Test
testCancelAllNotificationsImmediatelyAfterEnqueue()1008     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
1009         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1010         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1011                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1012         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1013         waitForIdle();
1014         StatusBarNotification[] notifs =
1015                 mBinderService.getActiveNotifications(sbn.getPackageName());
1016         assertEquals(0, notifs.length);
1017         assertEquals(0, mService.getNotificationRecordCount());
1018     }
1019 
1020     @Test
testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()1021     public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1022             throws Exception {
1023         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1024         sbn.getNotification().flags =
1025                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1026         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1027                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1028         mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
1029         waitForIdle();
1030         verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1031         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1032     }
1033 
1034     @Test
testUserInitiatedClearAll_noLeak()1035     public void testUserInitiatedClearAll_noLeak() throws Exception {
1036         final NotificationRecord n = generateNotificationRecord(
1037                 mTestNotificationChannel, 1, "group", true);
1038 
1039         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1040                 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
1041         waitForIdle();
1042 
1043         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1044                 n.getUserId());
1045         waitForIdle();
1046         StatusBarNotification[] notifs =
1047                 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1048         assertEquals(0, notifs.length);
1049         assertEquals(0, mService.getNotificationRecordCount());
1050         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1051         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1052         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
1053     }
1054 
1055     @Test
testCancelAllNotificationsCancelsChildren()1056     public void testCancelAllNotificationsCancelsChildren() throws Exception {
1057         final NotificationRecord parent = generateNotificationRecord(
1058                 mTestNotificationChannel, 1, "group1", true);
1059         final NotificationRecord child = generateNotificationRecord(
1060                 mTestNotificationChannel, 2, "group1", false);
1061 
1062         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1063                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1064         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1065                 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1066         waitForIdle();
1067 
1068         mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1069         waitForIdle();
1070         assertEquals(0, mService.getNotificationRecordCount());
1071     }
1072 
1073     @Test
testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()1074     public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1075         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1076         for (int i = 0; i < 10; i++) {
1077             mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1078                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1079         }
1080         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1081         waitForIdle();
1082 
1083         assertEquals(0, mService.getNotificationRecordCount());
1084     }
1085 
1086     @Test
testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()1087     public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1088         final NotificationRecord parent = generateNotificationRecord(
1089                 mTestNotificationChannel, 1, "group1", true);
1090         final NotificationRecord parentAsChild = generateNotificationRecord(
1091                 mTestNotificationChannel, 1, "group1", false);
1092         final NotificationRecord child = generateNotificationRecord(
1093                 mTestNotificationChannel, 2, "group1", false);
1094 
1095         // fully post parent notification
1096         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1097                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1098         waitForIdle();
1099 
1100         // enqueue the child several times
1101         for (int i = 0; i < 10; i++) {
1102             mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1103                     child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1104         }
1105         // make the parent a child, which will cancel the child notification
1106         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1107                 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1108                 parentAsChild.sbn.getUserId());
1109         waitForIdle();
1110 
1111         assertEquals(0, mService.getNotificationRecordCount());
1112     }
1113 
1114     @Test
testCancelAllNotifications_IgnoreForegroundService()1115     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1116         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1117         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1118         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1119                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1120         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1121         waitForIdle();
1122         StatusBarNotification[] notifs =
1123                 mBinderService.getActiveNotifications(sbn.getPackageName());
1124         assertEquals(1, notifs.length);
1125         assertEquals(1, mService.getNotificationRecordCount());
1126     }
1127 
1128     @Test
testCancelAllNotifications_IgnoreOtherPackages()1129     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1130         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1131         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1132         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1133                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1134         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1135         waitForIdle();
1136         StatusBarNotification[] notifs =
1137                 mBinderService.getActiveNotifications(sbn.getPackageName());
1138         assertEquals(1, notifs.length);
1139         assertEquals(1, mService.getNotificationRecordCount());
1140     }
1141 
1142     @Test
testCancelAllNotifications_NullPkgRemovesAll()1143     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1144         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1145         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1146                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1147         mBinderService.cancelAllNotifications(null, sbn.getUserId());
1148         waitForIdle();
1149         StatusBarNotification[] notifs =
1150                 mBinderService.getActiveNotifications(sbn.getPackageName());
1151         assertEquals(0, notifs.length);
1152         assertEquals(0, mService.getNotificationRecordCount());
1153     }
1154 
1155     @Test
testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()1156     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1157         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1158         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1159                 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
1160         // Null pkg is how we signal a user switch.
1161         mBinderService.cancelAllNotifications(null, sbn.getUserId());
1162         waitForIdle();
1163         StatusBarNotification[] notifs =
1164                 mBinderService.getActiveNotifications(sbn.getPackageName());
1165         assertEquals(1, notifs.length);
1166         assertEquals(1, mService.getNotificationRecordCount());
1167     }
1168 
1169     @Test
testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()1170     public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1171         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1172         sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1173         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1174                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1175         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1176         waitForIdle();
1177         StatusBarNotification[] notifs =
1178                 mBinderService.getActiveNotifications(sbn.getPackageName());
1179         assertEquals(0, notifs.length);
1180     }
1181 
1182     @Test
testCancelAllNotifications_CancelsNoClearFlag()1183     public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1184         final NotificationRecord notif = generateNotificationRecord(
1185                 mTestNotificationChannel, 1, "group", true);
1186         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1187         mService.addNotification(notif);
1188         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1189                 notif.getUserId(), 0, null);
1190         waitForIdle();
1191         StatusBarNotification[] notifs =
1192                 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1193         assertEquals(0, notifs.length);
1194     }
1195 
1196     @Test
testUserInitiatedCancelAllOnClearAll_NoClearFlag()1197     public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1198         final NotificationRecord notif = generateNotificationRecord(
1199                 mTestNotificationChannel, 1, "group", true);
1200         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1201         mService.addNotification(notif);
1202 
1203         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1204                 notif.getUserId());
1205         waitForIdle();
1206         StatusBarNotification[] notifs =
1207                 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1208         assertEquals(1, notifs.length);
1209     }
1210 
1211     @Test
testCancelAllCancelNotificationsFromListener_NoClearFlag()1212     public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1213         final NotificationRecord parent = generateNotificationRecord(
1214                 mTestNotificationChannel, 1, "group", true);
1215         final NotificationRecord child = generateNotificationRecord(
1216                 mTestNotificationChannel, 2, "group", false);
1217         final NotificationRecord child2 = generateNotificationRecord(
1218                 mTestNotificationChannel, 3, "group", false);
1219         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1220         final NotificationRecord newGroup = generateNotificationRecord(
1221                 mTestNotificationChannel, 4, "group2", false);
1222         mService.addNotification(parent);
1223         mService.addNotification(child);
1224         mService.addNotification(child2);
1225         mService.addNotification(newGroup);
1226         mService.getBinderService().cancelNotificationsFromListener(null, null);
1227         waitForIdle();
1228         StatusBarNotification[] notifs =
1229                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1230         assertEquals(1, notifs.length);
1231     }
1232 
1233     @Test
testUserInitiatedCancelAllWithGroup_NoClearFlag()1234     public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1235         final NotificationRecord parent = generateNotificationRecord(
1236                 mTestNotificationChannel, 1, "group", true);
1237         final NotificationRecord child = generateNotificationRecord(
1238                 mTestNotificationChannel, 2, "group", false);
1239         final NotificationRecord child2 = generateNotificationRecord(
1240                 mTestNotificationChannel, 3, "group", false);
1241         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1242         final NotificationRecord newGroup = generateNotificationRecord(
1243                 mTestNotificationChannel, 4, "group2", false);
1244         mService.addNotification(parent);
1245         mService.addNotification(child);
1246         mService.addNotification(child2);
1247         mService.addNotification(newGroup);
1248         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1249                 parent.getUserId());
1250         waitForIdle();
1251         StatusBarNotification[] notifs =
1252                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1253         assertEquals(1, notifs.length);
1254     }
1255 
1256     @Test
testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()1257     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
1258         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1259         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1260         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
1261                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1262         mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1263                 sbn.getUserId());
1264         waitForIdle();
1265         StatusBarNotification[] notifs =
1266                 mBinderService.getActiveNotifications(sbn.getPackageName());
1267         assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
1268     }
1269 
1270     @Test
testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()1271     public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1272         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1273         sbn.getNotification().flags =
1274                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1275         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1276                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1277         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
1278         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1279                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1280         mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
1281         waitForIdle();
1282         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1283         assertEquals(0, mService.getNotificationRecordCount());
1284     }
1285 
1286     @Test
testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()1287     public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1288             throws Exception {
1289         final NotificationRecord parent = generateNotificationRecord(
1290                 mTestNotificationChannel, 1, "group", true);
1291         final NotificationRecord child = generateNotificationRecord(
1292                 mTestNotificationChannel, 2, "group", false);
1293         final NotificationRecord child2 = generateNotificationRecord(
1294                 mTestNotificationChannel, 3, "group", false);
1295         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1296         final NotificationRecord newGroup = generateNotificationRecord(
1297                 mTestNotificationChannel, 4, "group2", false);
1298         mService.addNotification(parent);
1299         mService.addNotification(child);
1300         mService.addNotification(child2);
1301         mService.addNotification(newGroup);
1302         mService.getBinderService().cancelNotificationsFromListener(null, null);
1303         waitForIdle();
1304         StatusBarNotification[] notifs =
1305                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1306         assertEquals(0, notifs.length);
1307     }
1308 
1309     @Test
testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()1310     public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1311             throws Exception {
1312         final NotificationRecord parent = generateNotificationRecord(
1313                 mTestNotificationChannel, 1, "group", true);
1314         final NotificationRecord child = generateNotificationRecord(
1315                 mTestNotificationChannel, 2, "group", false);
1316         final NotificationRecord child2 = generateNotificationRecord(
1317                 mTestNotificationChannel, 3, "group", false);
1318         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1319         final NotificationRecord newGroup = generateNotificationRecord(
1320                 mTestNotificationChannel, 4, "group2", false);
1321         mService.addNotification(parent);
1322         mService.addNotification(child);
1323         mService.addNotification(child2);
1324         mService.addNotification(newGroup);
1325         String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1326                 child2.sbn.getKey(), newGroup.sbn.getKey()};
1327         mService.getBinderService().cancelNotificationsFromListener(null, keys);
1328         waitForIdle();
1329         StatusBarNotification[] notifs =
1330                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1331         assertEquals(1, notifs.length);
1332     }
1333 
1334     @Test
testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()1335     public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1336         final NotificationRecord parent = generateNotificationRecord(
1337                 mTestNotificationChannel, 1, "group", true);
1338         final NotificationRecord child = generateNotificationRecord(
1339                 mTestNotificationChannel, 2, "group", false);
1340         final NotificationRecord child2 = generateNotificationRecord(
1341                 mTestNotificationChannel, 3, "group", false);
1342         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1343         final NotificationRecord newGroup = generateNotificationRecord(
1344                 mTestNotificationChannel, 4, "group2", false);
1345         mService.addNotification(parent);
1346         mService.addNotification(child);
1347         mService.addNotification(child2);
1348         mService.addNotification(newGroup);
1349         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1350                 parent.getUserId());
1351         waitForIdle();
1352         StatusBarNotification[] notifs =
1353                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1354         assertEquals(0, notifs.length);
1355     }
1356 
1357     @Test
testFindGroupNotificationsLocked()1358     public void testFindGroupNotificationsLocked() throws Exception {
1359         // make sure the same notification can be found in both lists and returned
1360         final NotificationRecord group1 = generateNotificationRecord(
1361                 mTestNotificationChannel, 1, "group1", true);
1362         mService.addEnqueuedNotification(group1);
1363         mService.addNotification(group1);
1364 
1365         // should not be returned
1366         final NotificationRecord group2 = generateNotificationRecord(
1367                 mTestNotificationChannel, 2, "group2", true);
1368         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
1369                 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1370         waitForIdle();
1371 
1372         // should not be returned
1373         final NotificationRecord nonGroup = generateNotificationRecord(
1374                 mTestNotificationChannel, 3, null, false);
1375         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
1376                 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1377         waitForIdle();
1378 
1379         // same group, child, should be returned
1380         final NotificationRecord group1Child = generateNotificationRecord(
1381                 mTestNotificationChannel, 4, "group1", false);
1382         mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(),
1383                 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1384         waitForIdle();
1385 
1386         List<NotificationRecord> inGroup1 =
1387                 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
1388                         group1.sbn.getUserId());
1389         assertEquals(3, inGroup1.size());
1390         for (NotificationRecord record : inGroup1) {
1391             assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1392             assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1393         }
1394     }
1395 
1396     @Test
testCancelAllNotifications_CancelsNoClearFlagOnGoing()1397     public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1398         final NotificationRecord notif = generateNotificationRecord(
1399                 mTestNotificationChannel, 1, "group", true);
1400         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1401         mService.addNotification(notif);
1402         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1403                 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1404         waitForIdle();
1405         StatusBarNotification[] notifs =
1406                 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1407         assertEquals(0, notifs.length);
1408     }
1409 
1410     @Test
testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()1411     public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1412             throws Exception {
1413         final NotificationRecord parent = generateNotificationRecord(
1414                 mTestNotificationChannel, 1, "group", true);
1415         final NotificationRecord child = generateNotificationRecord(
1416                 mTestNotificationChannel, 2, "group", false);
1417         final NotificationRecord child2 = generateNotificationRecord(
1418                 mTestNotificationChannel, 3, "group", false);
1419         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1420         final NotificationRecord newGroup = generateNotificationRecord(
1421                 mTestNotificationChannel, 4, "group2", false);
1422         mService.addNotification(parent);
1423         mService.addNotification(child);
1424         mService.addNotification(child2);
1425         mService.addNotification(newGroup);
1426         String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1427                 child2.sbn.getKey(), newGroup.sbn.getKey()};
1428         mService.getBinderService().cancelNotificationsFromListener(null, keys);
1429         waitForIdle();
1430         StatusBarNotification[] notifs =
1431                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1432         assertEquals(0, notifs.length);
1433     }
1434 
1435     @Test
testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag()1436     public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1437         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1438         sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1439         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1440                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1441         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1442         waitForIdle();
1443         StatusBarNotification[] notifs =
1444                 mBinderService.getActiveNotifications(sbn.getPackageName());
1445         assertEquals(0, notifs.length);
1446     }
1447 
1448     @Test
testCancelAllNotifications_CancelsOnGoingFlag()1449     public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1450         final NotificationRecord notif = generateNotificationRecord(
1451                 mTestNotificationChannel, 1, "group", true);
1452         notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1453         mService.addNotification(notif);
1454         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1455                 notif.getUserId(), 0, null);
1456         waitForIdle();
1457         StatusBarNotification[] notifs =
1458                 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1459         assertEquals(0, notifs.length);
1460     }
1461 
1462     @Test
testUserInitiatedCancelAllOnClearAll_OnGoingFlag()1463     public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1464         final NotificationRecord notif = generateNotificationRecord(
1465                 mTestNotificationChannel, 1, "group", true);
1466         notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1467         mService.addNotification(notif);
1468 
1469         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1470                 notif.getUserId());
1471         waitForIdle();
1472         StatusBarNotification[] notifs =
1473                 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1474         assertEquals(1, notifs.length);
1475     }
1476 
1477     @Test
testCancelAllCancelNotificationsFromListener_OnGoingFlag()1478     public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1479         final NotificationRecord parent = generateNotificationRecord(
1480                 mTestNotificationChannel, 1, "group", true);
1481         final NotificationRecord child = generateNotificationRecord(
1482                 mTestNotificationChannel, 2, "group", false);
1483         final NotificationRecord child2 = generateNotificationRecord(
1484                 mTestNotificationChannel, 3, "group", false);
1485         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1486         final NotificationRecord newGroup = generateNotificationRecord(
1487                 mTestNotificationChannel, 4, "group2", false);
1488         mService.addNotification(parent);
1489         mService.addNotification(child);
1490         mService.addNotification(child2);
1491         mService.addNotification(newGroup);
1492         mService.getBinderService().cancelNotificationsFromListener(null, null);
1493         waitForIdle();
1494         StatusBarNotification[] notifs =
1495                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1496         assertEquals(1, notifs.length);
1497     }
1498 
1499     @Test
testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()1500     public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1501             throws Exception {
1502         final NotificationRecord parent = generateNotificationRecord(
1503                 mTestNotificationChannel, 1, "group", true);
1504         final NotificationRecord child = generateNotificationRecord(
1505                 mTestNotificationChannel, 2, "group", false);
1506         final NotificationRecord child2 = generateNotificationRecord(
1507                 mTestNotificationChannel, 3, "group", false);
1508         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1509         final NotificationRecord newGroup = generateNotificationRecord(
1510                 mTestNotificationChannel, 4, "group2", false);
1511         mService.addNotification(parent);
1512         mService.addNotification(child);
1513         mService.addNotification(child2);
1514         mService.addNotification(newGroup);
1515         String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1516                 child2.sbn.getKey(), newGroup.sbn.getKey()};
1517         mService.getBinderService().cancelNotificationsFromListener(null, keys);
1518         waitForIdle();
1519         StatusBarNotification[] notifs =
1520                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1521         assertEquals(0, notifs.length);
1522     }
1523 
1524     @Test
testUserInitiatedCancelAllWithGroup_OnGoingFlag()1525     public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1526         final NotificationRecord parent = generateNotificationRecord(
1527                 mTestNotificationChannel, 1, "group", true);
1528         final NotificationRecord child = generateNotificationRecord(
1529                 mTestNotificationChannel, 2, "group", false);
1530         final NotificationRecord child2 = generateNotificationRecord(
1531                 mTestNotificationChannel, 3, "group", false);
1532         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1533         final NotificationRecord newGroup = generateNotificationRecord(
1534                 mTestNotificationChannel, 4, "group2", false);
1535         mService.addNotification(parent);
1536         mService.addNotification(child);
1537         mService.addNotification(child2);
1538         mService.addNotification(newGroup);
1539         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1540                 parent.getUserId());
1541         waitForIdle();
1542         StatusBarNotification[] notifs =
1543                 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1544         assertEquals(1, notifs.length);
1545     }
1546 
1547     @Test
testTvExtenderChannelOverride_onTv()1548     public void testTvExtenderChannelOverride_onTv() throws Exception {
1549         mService.setIsTelevision(true);
1550         mService.setPreferencesHelper(mPreferencesHelper);
1551         when(mPreferencesHelper.getNotificationChannel(
1552                 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
1553                         new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
1554 
1555         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
1556         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
1557                 generateNotificationRecord(null, tv).getNotification(), 0);
1558         verify(mPreferencesHelper, times(1)).getNotificationChannel(
1559                 anyString(), anyInt(), eq("foo"), anyBoolean());
1560     }
1561 
1562     @Test
testTvExtenderChannelOverride_notOnTv()1563     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
1564         mService.setIsTelevision(false);
1565         mService.setPreferencesHelper(mPreferencesHelper);
1566         when(mPreferencesHelper.getNotificationChannel(
1567                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
1568                 mTestNotificationChannel);
1569 
1570         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
1571         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
1572                 generateNotificationRecord(null, tv).getNotification(), 0);
1573         verify(mPreferencesHelper, times(1)).getNotificationChannel(
1574                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
1575     }
1576 
1577     @Test
testUpdateAppNotifyCreatorBlock()1578     public void testUpdateAppNotifyCreatorBlock() throws Exception {
1579         mService.setPreferencesHelper(mPreferencesHelper);
1580 
1581         mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1582         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1583         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1584 
1585         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1586                 captor.getValue().getAction());
1587         assertEquals(PKG, captor.getValue().getPackage());
1588         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1589     }
1590 
1591     @Test
testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()1592     public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1593         mService.setPreferencesHelper(mPreferencesHelper);
1594 
1595         mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1596         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1597     }
1598 
1599     @Test
testUpdateAppNotifyCreatorUnblock()1600     public void testUpdateAppNotifyCreatorUnblock() throws Exception {
1601         mService.setPreferencesHelper(mPreferencesHelper);
1602 
1603         mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1604         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1605         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1606 
1607         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1608                 captor.getValue().getAction());
1609         assertEquals(PKG, captor.getValue().getPackage());
1610         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1611     }
1612 
1613     @Test
testUpdateChannelNotifyCreatorBlock()1614     public void testUpdateChannelNotifyCreatorBlock() throws Exception {
1615         mService.setPreferencesHelper(mPreferencesHelper);
1616         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1617                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1618                 .thenReturn(mTestNotificationChannel);
1619 
1620         NotificationChannel updatedChannel =
1621                 new NotificationChannel(mTestNotificationChannel.getId(),
1622                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1623 
1624         mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1625         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1626         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1627 
1628         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1629                 captor.getValue().getAction());
1630         assertEquals(PKG, captor.getValue().getPackage());
1631         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
1632                         NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
1633         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1634     }
1635 
1636     @Test
testUpdateChannelNotifyCreatorUnblock()1637     public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1638         NotificationChannel existingChannel =
1639                 new NotificationChannel(mTestNotificationChannel.getId(),
1640                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1641         mService.setPreferencesHelper(mPreferencesHelper);
1642         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1643                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1644                 .thenReturn(existingChannel);
1645 
1646         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1647         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1648         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1649 
1650         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1651                 captor.getValue().getAction());
1652         assertEquals(PKG, captor.getValue().getPackage());
1653         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
1654                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
1655         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1656     }
1657 
1658     @Test
testUpdateChannelNoNotifyCreatorOtherChanges()1659     public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1660         NotificationChannel existingChannel =
1661                 new NotificationChannel(mTestNotificationChannel.getId(),
1662                         mTestNotificationChannel.getName(), IMPORTANCE_MAX);
1663         mService.setPreferencesHelper(mPreferencesHelper);
1664         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1665                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1666                 .thenReturn(existingChannel);
1667 
1668         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1669         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1670     }
1671 
1672     @Test
testUpdateGroupNotifyCreatorBlock()1673     public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1674         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1675         mService.setPreferencesHelper(mPreferencesHelper);
1676         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
1677                 .thenReturn(existing);
1678 
1679         NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1680         updated.setBlocked(true);
1681 
1682         mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1683         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1684         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1685 
1686         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1687                 captor.getValue().getAction());
1688         assertEquals(PKG, captor.getValue().getPackage());
1689         assertEquals(existing.getId(), captor.getValue().getStringExtra(
1690                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
1691         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1692     }
1693 
1694     @Test
testUpdateGroupNotifyCreatorUnblock()1695     public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1696         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1697         existing.setBlocked(true);
1698         mService.setPreferencesHelper(mPreferencesHelper);
1699         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
1700                 .thenReturn(existing);
1701 
1702         mBinderService.updateNotificationChannelGroupForPackage(
1703                 PKG, 0, new NotificationChannelGroup("id", "name"));
1704         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1705         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1706 
1707         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1708                 captor.getValue().getAction());
1709         assertEquals(PKG, captor.getValue().getPackage());
1710         assertEquals(existing.getId(), captor.getValue().getStringExtra(
1711                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
1712         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1713     }
1714 
1715     @Test
testUpdateGroupNoNotifyCreatorOtherChanges()1716     public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1717         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1718         mService.setPreferencesHelper(mPreferencesHelper);
1719         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
1720                 .thenReturn(existing);
1721 
1722         mBinderService.updateNotificationChannelGroupForPackage(
1723                 PKG, 0, new NotificationChannelGroup("id", "new name"));
1724         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1725     }
1726 
1727     @Test
testCreateChannelNotifyListener()1728     public void testCreateChannelNotifyListener() throws Exception {
1729         List<String> associations = new ArrayList<>();
1730         associations.add("a");
1731         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1732         mService.setPreferencesHelper(mPreferencesHelper);
1733         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1734                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1735                 .thenReturn(mTestNotificationChannel);
1736         NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
1737         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1738                 eq(channel2.getId()), anyBoolean()))
1739                 .thenReturn(channel2);
1740         when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1741                 eq(channel2), anyBoolean(), anyBoolean()))
1742                 .thenReturn(true);
1743 
1744         reset(mListeners);
1745         mBinderService.createNotificationChannels(PKG,
1746                 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
1747         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
1748                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1749                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1750         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
1751                 eq(Process.myUserHandle()), eq(channel2),
1752                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1753     }
1754 
1755     @Test
testCreateChannelGroupNotifyListener()1756     public void testCreateChannelGroupNotifyListener() throws Exception {
1757         List<String> associations = new ArrayList<>();
1758         associations.add("a");
1759         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1760         mService.setPreferencesHelper(mPreferencesHelper);
1761         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1762         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1763 
1764         reset(mListeners);
1765         mBinderService.createNotificationChannelGroups(PKG,
1766                 new ParceledListSlice(Arrays.asList(group1, group2)));
1767         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
1768                 eq(Process.myUserHandle()), eq(group1),
1769                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1770         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
1771                 eq(Process.myUserHandle()), eq(group2),
1772                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1773     }
1774 
1775     @Test
testUpdateChannelNotifyListener()1776     public void testUpdateChannelNotifyListener() throws Exception {
1777         List<String> associations = new ArrayList<>();
1778         associations.add("a");
1779         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1780         mService.setPreferencesHelper(mPreferencesHelper);
1781         mTestNotificationChannel.setLightColor(Color.CYAN);
1782         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1783                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1784                 .thenReturn(mTestNotificationChannel);
1785 
1786         reset(mListeners);
1787         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1788         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
1789                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1790                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1791     }
1792 
1793     @Test
testDeleteChannelNotifyListener()1794     public void testDeleteChannelNotifyListener() throws Exception {
1795         List<String> associations = new ArrayList<>();
1796         associations.add("a");
1797         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1798         mService.setPreferencesHelper(mPreferencesHelper);
1799         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1800                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1801                 .thenReturn(mTestNotificationChannel);
1802         reset(mListeners);
1803         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
1804         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
1805                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1806                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1807     }
1808 
1809     @Test
testDeleteChannelGroupNotifyListener()1810     public void testDeleteChannelGroupNotifyListener() throws Exception {
1811         List<String> associations = new ArrayList<>();
1812         associations.add("a");
1813         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1814         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
1815         mService.setPreferencesHelper(mPreferencesHelper);
1816         when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
1817                 .thenReturn(ncg);
1818         reset(mListeners);
1819         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
1820         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
1821                 eq(Process.myUserHandle()), eq(ncg),
1822                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1823     }
1824 
1825     @Test
testUpdateNotificationChannelFromPrivilegedListener_success()1826     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
1827         mService.setPreferencesHelper(mPreferencesHelper);
1828         List<String> associations = new ArrayList<>();
1829         associations.add("a");
1830         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1831         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
1832                 eq(mTestNotificationChannel.getId()), anyBoolean()))
1833                 .thenReturn(mTestNotificationChannel);
1834 
1835         mBinderService.updateNotificationChannelFromPrivilegedListener(
1836                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
1837 
1838         verify(mPreferencesHelper, times(1)).updateNotificationChannel(
1839                 anyString(), anyInt(), any(), anyBoolean());
1840 
1841         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
1842                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1843                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1844     }
1845 
1846     @Test
testUpdateNotificationChannelFromPrivilegedListener_noAccess()1847     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
1848         mService.setPreferencesHelper(mPreferencesHelper);
1849         List<String> associations = new ArrayList<>();
1850         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1851 
1852         try {
1853             mBinderService.updateNotificationChannelFromPrivilegedListener(
1854                     null, PKG, Process.myUserHandle(), mTestNotificationChannel);
1855             fail("listeners that don't have a companion device shouldn't be able to call this");
1856         } catch (SecurityException e) {
1857             // pass
1858         }
1859 
1860         verify(mPreferencesHelper, never()).updateNotificationChannel(
1861                 anyString(), anyInt(), any(), anyBoolean());
1862 
1863         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
1864                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1865                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1866     }
1867 
1868     @Test
testUpdateNotificationChannelFromPrivilegedListener_badUser()1869     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
1870         mService.setPreferencesHelper(mPreferencesHelper);
1871         List<String> associations = new ArrayList<>();
1872         associations.add("a");
1873         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1874         mListener = mock(ManagedServices.ManagedServiceInfo.class);
1875         mListener.component = new ComponentName(PKG, PKG);
1876         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
1877         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
1878 
1879         try {
1880             mBinderService.updateNotificationChannelFromPrivilegedListener(
1881                     null, PKG, UserHandle.ALL, mTestNotificationChannel);
1882             fail("incorrectly allowed a change to a user listener cannot see");
1883         } catch (SecurityException e) {
1884             // pass
1885         }
1886 
1887         verify(mPreferencesHelper, never()).updateNotificationChannel(
1888                 anyString(), anyInt(), any(), anyBoolean());
1889 
1890         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
1891                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1892                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1893     }
1894 
1895     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_success()1896     public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
1897         mService.setPreferencesHelper(mPreferencesHelper);
1898         List<String> associations = new ArrayList<>();
1899         associations.add("a");
1900         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1901 
1902         mBinderService.getNotificationChannelsFromPrivilegedListener(
1903                 null, PKG, Process.myUserHandle());
1904 
1905         verify(mPreferencesHelper, times(1)).getNotificationChannels(
1906                 anyString(), anyInt(), anyBoolean());
1907     }
1908 
1909     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()1910     public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
1911         mService.setPreferencesHelper(mPreferencesHelper);
1912         List<String> associations = new ArrayList<>();
1913         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1914 
1915         try {
1916             mBinderService.getNotificationChannelsFromPrivilegedListener(
1917                     null, PKG, Process.myUserHandle());
1918             fail("listeners that don't have a companion device shouldn't be able to call this");
1919         } catch (SecurityException e) {
1920             // pass
1921         }
1922 
1923         verify(mPreferencesHelper, never()).getNotificationChannels(
1924                 anyString(), anyInt(), anyBoolean());
1925     }
1926 
1927     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_success()1928     public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
1929             throws Exception {
1930         mService.setPreferencesHelper(mPreferencesHelper);
1931         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1932         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
1933 
1934         mBinderService.getNotificationChannelsFromPrivilegedListener(
1935                 null, PKG, Process.myUserHandle());
1936 
1937         verify(mPreferencesHelper, times(1)).getNotificationChannels(
1938                 anyString(), anyInt(), anyBoolean());
1939     }
1940 
1941     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()1942     public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
1943             throws Exception {
1944         mService.setPreferencesHelper(mPreferencesHelper);
1945         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1946         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
1947 
1948         try {
1949             mBinderService.getNotificationChannelsFromPrivilegedListener(
1950                     null, PKG, Process.myUserHandle());
1951             fail("listeners that don't have a companion device shouldn't be able to call this");
1952         } catch (SecurityException e) {
1953             // pass
1954         }
1955 
1956         verify(mPreferencesHelper, never()).getNotificationChannels(
1957                 anyString(), anyInt(), anyBoolean());
1958     }
1959 
1960     @Test
testGetNotificationChannelFromPrivilegedListener_badUser()1961     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
1962         mService.setPreferencesHelper(mPreferencesHelper);
1963         List<String> associations = new ArrayList<>();
1964         associations.add("a");
1965         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1966         mListener = mock(ManagedServices.ManagedServiceInfo.class);
1967         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
1968         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
1969 
1970         try {
1971             mBinderService.getNotificationChannelsFromPrivilegedListener(
1972                     null, PKG, Process.myUserHandle());
1973             fail("listener getting channels from a user they cannot see");
1974         } catch (SecurityException e) {
1975             // pass
1976         }
1977 
1978         verify(mPreferencesHelper, never()).getNotificationChannels(
1979                 anyString(), anyInt(), anyBoolean());
1980     }
1981 
1982     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_success()1983     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
1984         mService.setPreferencesHelper(mPreferencesHelper);
1985         List<String> associations = new ArrayList<>();
1986         associations.add("a");
1987         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
1988 
1989         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1990                 null, PKG, Process.myUserHandle());
1991 
1992         verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
1993     }
1994 
1995     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()1996     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
1997         mService.setPreferencesHelper(mPreferencesHelper);
1998         List<String> associations = new ArrayList<>();
1999         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
2000 
2001         try {
2002             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2003                     null, PKG, Process.myUserHandle());
2004             fail("listeners that don't have a companion device shouldn't be able to call this");
2005         } catch (SecurityException e) {
2006             // pass
2007         }
2008 
2009         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
2010     }
2011 
2012     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_badUser()2013     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
2014         mService.setPreferencesHelper(mPreferencesHelper);
2015         List<String> associations = new ArrayList<>();
2016         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
2017         mListener = mock(ManagedServices.ManagedServiceInfo.class);
2018         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
2019         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
2020         try {
2021             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2022                     null, PKG, Process.myUserHandle());
2023             fail("listeners that don't have a companion device shouldn't be able to call this");
2024         } catch (SecurityException e) {
2025             // pass
2026         }
2027 
2028         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
2029     }
2030 
2031     @Test
testHasCompanionDevice_failure()2032     public void testHasCompanionDevice_failure() throws Exception {
2033         when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2034                 new IllegalArgumentException());
2035         mService.hasCompanionDevice(mListener);
2036     }
2037 
2038     @Test
testHasCompanionDevice_noService()2039     public void testHasCompanionDevice_noService() {
2040         mService = new TestableNotificationManagerService(mContext);
2041 
2042         assertFalse(mService.hasCompanionDevice(mListener));
2043     }
2044 
2045     @Test
testSnoozeRunnable_snoozeNonGrouped()2046     public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2047         final NotificationRecord nonGrouped = generateNotificationRecord(
2048                 mTestNotificationChannel, 1, null, false);
2049         final NotificationRecord grouped = generateNotificationRecord(
2050                 mTestNotificationChannel, 2, "group", false);
2051         mService.addNotification(grouped);
2052         mService.addNotification(nonGrouped);
2053 
2054         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2055                 mService.new SnoozeNotificationRunnable(
2056                         nonGrouped.getKey(), 100, null);
2057         snoozeNotificationRunnable.run();
2058 
2059         // only snooze the one notification
2060         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2061         assertTrue(nonGrouped.getStats().hasSnoozed());
2062     }
2063 
2064     @Test
testSnoozeRunnable_snoozeSummary_withChildren()2065     public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2066         final NotificationRecord parent = generateNotificationRecord(
2067                 mTestNotificationChannel, 1, "group", true);
2068         final NotificationRecord child = generateNotificationRecord(
2069                 mTestNotificationChannel, 2, "group", false);
2070         final NotificationRecord child2 = generateNotificationRecord(
2071                 mTestNotificationChannel, 3, "group", false);
2072         mService.addNotification(parent);
2073         mService.addNotification(child);
2074         mService.addNotification(child2);
2075 
2076         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2077                 mService.new SnoozeNotificationRunnable(
2078                         parent.getKey(), 100, null);
2079         snoozeNotificationRunnable.run();
2080 
2081         // snooze parent and children
2082         verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2083     }
2084 
2085     @Test
testSnoozeRunnable_snoozeGroupChild_fellowChildren()2086     public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2087         final NotificationRecord parent = generateNotificationRecord(
2088                 mTestNotificationChannel, 1, "group", true);
2089         final NotificationRecord child = generateNotificationRecord(
2090                 mTestNotificationChannel, 2, "group", false);
2091         final NotificationRecord child2 = generateNotificationRecord(
2092                 mTestNotificationChannel, 3, "group", false);
2093         mService.addNotification(parent);
2094         mService.addNotification(child);
2095         mService.addNotification(child2);
2096 
2097         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2098                 mService.new SnoozeNotificationRunnable(
2099                         child2.getKey(), 100, null);
2100         snoozeNotificationRunnable.run();
2101 
2102         // only snooze the one child
2103         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2104     }
2105 
2106     @Test
testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()2107     public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2108         final NotificationRecord parent = generateNotificationRecord(
2109                 mTestNotificationChannel, 1, "group", true);
2110         assertTrue(parent.sbn.getNotification().isGroupSummary());
2111         final NotificationRecord child = generateNotificationRecord(
2112                 mTestNotificationChannel, 2, "group", false);
2113         mService.addNotification(parent);
2114         mService.addNotification(child);
2115 
2116         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2117                 mService.new SnoozeNotificationRunnable(
2118                         child.getKey(), 100, null);
2119         snoozeNotificationRunnable.run();
2120 
2121         // snooze child and summary
2122         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2123     }
2124 
2125     @Test
testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()2126     public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2127         final NotificationRecord child = generateNotificationRecord(
2128                 mTestNotificationChannel, 2, "group", false);
2129         mService.addNotification(child);
2130 
2131         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2132                 mService.new SnoozeNotificationRunnable(
2133                         child.getKey(), 100, null);
2134         snoozeNotificationRunnable.run();
2135 
2136         // snooze child only
2137         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2138     }
2139 
2140     @Test
testPostGroupChild_unsnoozeParent()2141     public void testPostGroupChild_unsnoozeParent() throws Exception {
2142         final NotificationRecord child = generateNotificationRecord(
2143                 mTestNotificationChannel, 2, "group", false);
2144 
2145         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2146                 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2147         waitForIdle();
2148 
2149         verify(mSnoozeHelper, times(1)).repostGroupSummary(
2150                 anyString(), anyInt(), eq(child.getGroupKey()));
2151     }
2152 
2153     @Test
testPostNonGroup_noUnsnoozing()2154     public void testPostNonGroup_noUnsnoozing() throws Exception {
2155         final NotificationRecord record = generateNotificationRecord(
2156                 mTestNotificationChannel, 2, null, false);
2157 
2158         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2159                 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2160         waitForIdle();
2161 
2162         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2163     }
2164 
2165     @Test
testPostGroupSummary_noUnsnoozing()2166     public void testPostGroupSummary_noUnsnoozing() throws Exception {
2167         final NotificationRecord parent = generateNotificationRecord(
2168                 mTestNotificationChannel, 2, "group", true);
2169 
2170         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2171                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2172         waitForIdle();
2173 
2174         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2175     }
2176 
2177     @Test
testSetListenerAccessForUser()2178     public void testSetListenerAccessForUser() throws Exception {
2179         UserHandle user = UserHandle.of(10);
2180         ComponentName c = ComponentName.unflattenFromString("package/Component");
2181         mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2182 
2183 
2184         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2185         verify(mListeners, times(1)).setPackageOrComponentEnabled(
2186                 c.flattenToString(), user.getIdentifier(), true, true);
2187         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2188                 c.flattenToString(), user.getIdentifier(), false, true);
2189         verify(mAssistants, never()).setPackageOrComponentEnabled(
2190                 any(), anyInt(), anyBoolean(), anyBoolean());
2191     }
2192 
2193     @Test
testSetAssistantAccessForUser()2194     public void testSetAssistantAccessForUser() throws Exception {
2195         UserHandle user = UserHandle.of(10);
2196         List<UserInfo> uis = new ArrayList<>();
2197         UserInfo ui = new UserInfo();
2198         ui.id = 10;
2199         uis.add(ui);
2200         ComponentName c = ComponentName.unflattenFromString("package/Component");
2201         when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2202 
2203         mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
2204 
2205         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2206         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2207                 c.flattenToString(), user.getIdentifier(), true, true);
2208         verify(mAssistants).setUserSet(10, true);
2209         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2210                 c.flattenToString(), user.getIdentifier(), false, true);
2211         verify(mListeners, never()).setPackageOrComponentEnabled(
2212                 any(), anyInt(), anyBoolean(), anyBoolean());
2213     }
2214 
2215     @Test
testGetAssistantAllowedForUser()2216     public void testGetAssistantAllowedForUser() throws Exception {
2217         UserHandle user = UserHandle.of(10);
2218         try {
2219             mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2220         } catch (IllegalStateException e) {
2221             if (!e.getMessage().contains("At most one NotificationAssistant")) {
2222                 throw e;
2223             }
2224         }
2225         verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2226     }
2227 
2228     @Test
testGetAssistantAllowed()2229     public void testGetAssistantAllowed() throws Exception {
2230         try {
2231             mBinderService.getAllowedNotificationAssistant();
2232         } catch (IllegalStateException e) {
2233             if (!e.getMessage().contains("At most one NotificationAssistant")) {
2234                 throw e;
2235             }
2236         }
2237         verify(mAssistants, times(1)).getAllowedComponents(0);
2238     }
2239 
2240     @Test
testSetDndAccessForUser()2241     public void testSetDndAccessForUser() throws Exception {
2242         UserHandle user = UserHandle.of(10);
2243         ComponentName c = ComponentName.unflattenFromString("package/Component");
2244         mBinderService.setNotificationPolicyAccessGrantedForUser(
2245                 c.getPackageName(), user.getIdentifier(), true);
2246 
2247         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2248         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2249                 c.getPackageName(), user.getIdentifier(), true, true);
2250         verify(mAssistants, never()).setPackageOrComponentEnabled(
2251                 any(), anyInt(), anyBoolean(), anyBoolean());
2252         verify(mListeners, never()).setPackageOrComponentEnabled(
2253                 any(), anyInt(), anyBoolean(), anyBoolean());
2254     }
2255 
2256     @Test
testSetListenerAccess()2257     public void testSetListenerAccess() throws Exception {
2258         ComponentName c = ComponentName.unflattenFromString("package/Component");
2259         mBinderService.setNotificationListenerAccessGranted(c, true);
2260 
2261         verify(mListeners, times(1)).setPackageOrComponentEnabled(
2262                 c.flattenToString(), 0, true, true);
2263         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2264                 c.flattenToString(), 0, false, true);
2265         verify(mAssistants, never()).setPackageOrComponentEnabled(
2266                 any(), anyInt(), anyBoolean(), anyBoolean());
2267     }
2268 
2269     @Test
testSetAssistantAccess()2270     public void testSetAssistantAccess() throws Exception {
2271         List<UserInfo> uis = new ArrayList<>();
2272         UserInfo ui = new UserInfo();
2273         ui.id = 0;
2274         uis.add(ui);
2275         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2276         ComponentName c = ComponentName.unflattenFromString("package/Component");
2277 
2278         mBinderService.setNotificationAssistantAccessGranted(c, true);
2279 
2280         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2281                 c.flattenToString(), 0, true, true);
2282         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2283                 c.flattenToString(), 0, false, true);
2284         verify(mListeners, never()).setPackageOrComponentEnabled(
2285                 any(), anyInt(), anyBoolean(), anyBoolean());
2286     }
2287 
2288     @Test
testSetAssistantAccess_multiProfile()2289     public void testSetAssistantAccess_multiProfile() throws Exception {
2290         List<UserInfo> uis = new ArrayList<>();
2291         UserInfo ui = new UserInfo();
2292         ui.id = 0;
2293         uis.add(ui);
2294         UserInfo ui10 = new UserInfo();
2295         ui10.id = 10;
2296         uis.add(ui10);
2297         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2298         ComponentName c = ComponentName.unflattenFromString("package/Component");
2299 
2300         mBinderService.setNotificationAssistantAccessGranted(c, true);
2301 
2302         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2303                 c.flattenToString(), 0, true, true);
2304         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2305                 c.flattenToString(), 10, true, true);
2306         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2307                 c.flattenToString(), 0, false, true);
2308         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2309                 c.flattenToString(), 10, false, true);
2310         verify(mListeners, never()).setPackageOrComponentEnabled(
2311                 any(), anyInt(), anyBoolean(), anyBoolean());
2312     }
2313 
2314     @Test
testSetAssistantAccess_nullWithAllowedAssistant()2315     public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2316         ArrayList<ComponentName> componentList = new ArrayList<>();
2317         ComponentName c = ComponentName.unflattenFromString("package/Component");
2318         componentList.add(c);
2319         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2320         List<UserInfo> uis = new ArrayList<>();
2321         UserInfo ui = new UserInfo();
2322         ui.id = 0;
2323         uis.add(ui);
2324         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2325 
2326         mBinderService.setNotificationAssistantAccessGranted(null, true);
2327 
2328         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2329                 c.flattenToString(), 0, true, false);
2330         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2331                 c.flattenToString(), 0, false,  false);
2332         verify(mListeners, never()).setPackageOrComponentEnabled(
2333                 any(), anyInt(), anyBoolean(), anyBoolean());
2334     }
2335 
2336     @Test
testSetAssistantAccessForUser_nullWithAllowedAssistant()2337     public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
2338         List<UserInfo> uis = new ArrayList<>();
2339         UserInfo ui = new UserInfo();
2340         ui.id = 10;
2341         uis.add(ui);
2342         UserHandle user = ui.getUserHandle();
2343         ArrayList<ComponentName> componentList = new ArrayList<>();
2344         ComponentName c = ComponentName.unflattenFromString("package/Component");
2345         componentList.add(c);
2346         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2347         when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2348 
2349         mBinderService.setNotificationAssistantAccessGrantedForUser(
2350                 null, user.getIdentifier(), true);
2351 
2352         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2353                 c.flattenToString(), user.getIdentifier(), true, false);
2354         verify(mAssistants).setUserSet(10, true);
2355         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2356                 c.flattenToString(), user.getIdentifier(), false,  false);
2357         verify(mListeners, never()).setPackageOrComponentEnabled(
2358                 any(), anyInt(), anyBoolean(), anyBoolean());
2359     }
2360 
2361     @Test
testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()2362     public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2363             throws Exception {
2364         List<UserInfo> uis = new ArrayList<>();
2365         UserInfo ui = new UserInfo();
2366         ui.id = 0;
2367         uis.add(ui);
2368         UserInfo ui10 = new UserInfo();
2369         ui10.id = 10;
2370         uis.add(ui10);
2371         UserHandle user = ui.getUserHandle();
2372         ArrayList<ComponentName> componentList = new ArrayList<>();
2373         ComponentName c = ComponentName.unflattenFromString("package/Component");
2374         componentList.add(c);
2375         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2376         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2377 
2378         mBinderService.setNotificationAssistantAccessGrantedForUser(
2379                     null, user.getIdentifier(), true);
2380 
2381         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2382                 c.flattenToString(), user.getIdentifier(), true, false);
2383         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2384                 c.flattenToString(), ui10.id, true, false);
2385         verify(mAssistants).setUserSet(0, true);
2386         verify(mAssistants).setUserSet(10, true);
2387         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2388                 c.flattenToString(), user.getIdentifier(), false,  false);
2389         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2390                 c.flattenToString(), ui10.id, false,  false);
2391         verify(mListeners, never()).setPackageOrComponentEnabled(
2392                 any(), anyInt(), anyBoolean(), anyBoolean());
2393     }
2394 
2395     @Test
testSetDndAccess()2396     public void testSetDndAccess() throws Exception {
2397         ComponentName c = ComponentName.unflattenFromString("package/Component");
2398 
2399         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2400 
2401         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2402                 c.getPackageName(), 0, true, true);
2403         verify(mAssistants, never()).setPackageOrComponentEnabled(
2404                 any(), anyInt(), anyBoolean(), anyBoolean());
2405         verify(mListeners, never()).setPackageOrComponentEnabled(
2406                 any(), anyInt(), anyBoolean(), anyBoolean());
2407     }
2408 
2409     @Test
testSetListenerAccess_doesNothingOnLowRam()2410     public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2411         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2412         ComponentName c = ComponentName.unflattenFromString("package/Component");
2413         mBinderService.setNotificationListenerAccessGranted(c, true);
2414 
2415         verify(mListeners, never()).setPackageOrComponentEnabled(
2416                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2417         verify(mConditionProviders, never()).setPackageOrComponentEnabled(
2418                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2419         verify(mAssistants, never()).setPackageOrComponentEnabled(
2420                 any(), anyInt(), anyBoolean(), anyBoolean());
2421     }
2422 
2423     @Test
testSetAssistantAccess_doesNothingOnLowRam()2424     public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2425         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2426         ComponentName c = ComponentName.unflattenFromString("package/Component");
2427         List<UserInfo> uis = new ArrayList<>();
2428         UserInfo ui = new UserInfo();
2429         ui.id = 0;
2430         uis.add(ui);
2431         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2432 
2433         mBinderService.setNotificationAssistantAccessGranted(c, true);
2434 
2435         verify(mListeners, never()).setPackageOrComponentEnabled(
2436                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2437         verify(mConditionProviders, never()).setPackageOrComponentEnabled(
2438                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2439         verify(mAssistants, never()).setPackageOrComponentEnabled(
2440                 any(), anyInt(), anyBoolean(), anyBoolean());
2441     }
2442 
2443     @Test
testSetDndAccess_doesNothingOnLowRam()2444     public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2445         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2446         ComponentName c = ComponentName.unflattenFromString("package/Component");
2447         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2448 
2449         verify(mListeners, never()).setPackageOrComponentEnabled(
2450                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2451         verify(mConditionProviders, never()).setPackageOrComponentEnabled(
2452                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2453         verify(mAssistants, never()).setPackageOrComponentEnabled(
2454                 any(), anyInt(), anyBoolean(), anyBoolean());
2455     }
2456 
2457     @Test
testSetListenerAccess_doesNothingOnLowRam_exceptWatch()2458     public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2459         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2460         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2461         ComponentName c = ComponentName.unflattenFromString("package/Component");
2462 
2463         mBinderService.setNotificationListenerAccessGranted(c, true);
2464 
2465         verify(mListeners, times(1)).setPackageOrComponentEnabled(
2466                 c.flattenToString(), 0, true, true);
2467         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2468                 c.flattenToString(), 0, false, true);
2469         verify(mAssistants, never()).setPackageOrComponentEnabled(
2470                 any(), anyInt(), anyBoolean(), anyBoolean());
2471     }
2472 
2473     @Test
testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()2474     public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2475         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2476         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2477         ComponentName c = ComponentName.unflattenFromString("package/Component");
2478         List<UserInfo> uis = new ArrayList<>();
2479         UserInfo ui = new UserInfo();
2480         ui.id = 0;
2481         uis.add(ui);
2482         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2483 
2484         mBinderService.setNotificationAssistantAccessGranted(c, true);
2485 
2486         verify(mListeners, never()).setPackageOrComponentEnabled(
2487                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2488         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2489                 c.flattenToString(), 0, false, true);
2490         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2491                 c.flattenToString(), 0, true, true);
2492     }
2493 
2494     @Test
testSetDndAccess_doesNothingOnLowRam_exceptWatch()2495     public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2496         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2497         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2498         ComponentName c = ComponentName.unflattenFromString("package/Component");
2499 
2500         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2501 
2502         verify(mListeners, never()).setPackageOrComponentEnabled(
2503                 anyString(), anyInt(), anyBoolean(), anyBoolean());
2504         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2505                 c.getPackageName(), 0, true, true);
2506         verify(mAssistants, never()).setPackageOrComponentEnabled(
2507                 any(), anyInt(), anyBoolean(), anyBoolean());
2508     }
2509 
2510     @Test
testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups()2511     public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2512         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2513         mService.addEnqueuedNotification(r);
2514         NotificationManagerService.PostNotificationRunnable runnable =
2515                 mService.new PostNotificationRunnable(r.getKey());
2516         runnable.run();
2517         waitForIdle();
2518 
2519         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
2520     }
2521 
2522     @Test
testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()2523     public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2524             throws Exception {
2525         NotificationRecord r =
2526                 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
2527         mService.addNotification(r);
2528 
2529         r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2530         mService.addEnqueuedNotification(r);
2531         NotificationManagerService.PostNotificationRunnable runnable =
2532                 mService.new PostNotificationRunnable(r.getKey());
2533         runnable.run();
2534         waitForIdle();
2535 
2536         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
2537     }
2538 
2539     @Test
testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()2540     public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2541             throws Exception {
2542         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2543                 false);
2544         mService.addNotification(r);
2545         mService.addEnqueuedNotification(r);
2546 
2547         NotificationManagerService.PostNotificationRunnable runnable =
2548                 mService.new PostNotificationRunnable(r.getKey());
2549         runnable.run();
2550         waitForIdle();
2551 
2552         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2553     }
2554 
2555     @Test
testDontAutogroupIfCritical()2556     public void testDontAutogroupIfCritical() throws Exception {
2557         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2558         r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2559         mService.addEnqueuedNotification(r);
2560         NotificationManagerService.PostNotificationRunnable runnable =
2561                 mService.new PostNotificationRunnable(r.getKey());
2562         runnable.run();
2563 
2564         r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2565         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2566         runnable = mService.new PostNotificationRunnable(r.getKey());
2567         mService.addEnqueuedNotification(r);
2568 
2569         runnable.run();
2570         waitForIdle();
2571 
2572         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2573     }
2574 
2575     @Test
testNoFakeColorizedPermission()2576     public void testNoFakeColorizedPermission() throws Exception {
2577         when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2578         Notification.Builder nb = new Notification.Builder(mContext,
2579                 mTestNotificationChannel.getId())
2580                 .setContentTitle("foo")
2581                 .setColorized(true)
2582                 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2583                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
2584         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
2585                 nb.build(), new UserHandle(mUid), null, 0);
2586         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2587 
2588         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2589                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2590         waitForIdle();
2591 
2592         NotificationRecord posted = mService.findNotificationLocked(
2593                 PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
2594 
2595         assertFalse(posted.getNotification().isColorized());
2596     }
2597 
2598     @Test
testGetNotificationCountLocked()2599     public void testGetNotificationCountLocked() throws Exception {
2600         for (int i = 0; i < 20; i++) {
2601             NotificationRecord r =
2602                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
2603             mService.addEnqueuedNotification(r);
2604         }
2605         for (int i = 0; i < 20; i++) {
2606             NotificationRecord r =
2607                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
2608             mService.addNotification(r);
2609         }
2610 
2611         // another package
2612         Notification n =
2613                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2614                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2615                 .build();
2616 
2617         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2618                 n, new UserHandle(mUid), null, 0);
2619         NotificationRecord otherPackage =
2620                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2621         mService.addEnqueuedNotification(otherPackage);
2622         mService.addNotification(otherPackage);
2623 
2624         // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
2625         int userId = new UserHandle(mUid).getIdentifier();
2626         assertEquals(40,
2627                 mService.getNotificationCountLocked(PKG, userId, 0, null));
2628         assertEquals(40,
2629                 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
2630         assertEquals(2,
2631                 mService.getNotificationCountLocked("a", userId, 0, "banana"));
2632 
2633         // exclude a known notification - it's excluded from only the posted list, not enqueued
2634         assertEquals(39,
2635                 mService.getNotificationCountLocked(PKG, userId, 0, "tag"));
2636     }
2637 
2638     @Test
testAddAutogroup_requestsSort()2639     public void testAddAutogroup_requestsSort() throws Exception {
2640         RankingHandler rh = mock(RankingHandler.class);
2641         mService.setRankingHandler(rh);
2642 
2643         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2644         mService.addNotification(r);
2645         mService.addAutogroupKeyLocked(r.getKey());
2646 
2647         verify(rh, times(1)).requestSort();
2648     }
2649 
2650     @Test
testRemoveAutogroup_requestsSort()2651     public void testRemoveAutogroup_requestsSort() throws Exception {
2652         RankingHandler rh = mock(RankingHandler.class);
2653         mService.setRankingHandler(rh);
2654 
2655         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2656         r.setOverrideGroupKey("TEST");
2657         mService.addNotification(r);
2658         mService.removeAutogroupKeyLocked(r.getKey());
2659 
2660         verify(rh, times(1)).requestSort();
2661     }
2662 
2663     @Test
testReaddAutogroup_noSort()2664     public void testReaddAutogroup_noSort() throws Exception {
2665         RankingHandler rh = mock(RankingHandler.class);
2666         mService.setRankingHandler(rh);
2667 
2668         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2669         r.setOverrideGroupKey("TEST");
2670         mService.addNotification(r);
2671         mService.addAutogroupKeyLocked(r.getKey());
2672 
2673         verify(rh, never()).requestSort();
2674     }
2675 
2676     @Test
testHandleRankingSort_sendsUpdateOnSignalExtractorChange()2677     public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
2678         mService.setPreferencesHelper(mPreferencesHelper);
2679         NotificationManagerService.WorkerHandler handler = mock(
2680                 NotificationManagerService.WorkerHandler.class);
2681         mService.setHandler(handler);
2682 
2683         Map<String, Answer> answers = getSignalExtractorSideEffects();
2684         for (String message : answers.keySet()) {
2685             mService.clearNotifications();
2686             final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2687             mService.addNotification(r);
2688 
2689             doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2690 
2691             mService.handleRankingSort();
2692         }
2693         verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2694     }
2695 
2696     @Test
testHandleRankingSort_noUpdateWhenNoSignalChange()2697     public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
2698         mService.setRankingHelper(mRankingHelper);
2699         NotificationManagerService.WorkerHandler handler = mock(
2700                 NotificationManagerService.WorkerHandler.class);
2701         mService.setHandler(handler);
2702 
2703         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2704         mService.addNotification(r);
2705 
2706         mService.handleRankingSort();
2707         verify(handler, never()).scheduleSendRankingUpdate();
2708     }
2709 
2710     @Test
testReadPolicyXml_readApprovedServicesFromXml()2711     public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
2712         final String upgradeXml = "<notification-policy version=\"1\">"
2713                 + "<ranking></ranking>"
2714                 + "<enabled_listeners>"
2715                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2716                 + "</enabled_listeners>"
2717                 + "<enabled_assistants>"
2718                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2719                 + "</enabled_assistants>"
2720                 + "<dnd_apps>"
2721                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2722                 + "</dnd_apps>"
2723                 + "</notification-policy>";
2724         mService.readPolicyXml(
2725                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2726                 false,
2727                 UserHandle.USER_ALL);
2728         verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2729         verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2730         verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2731 
2732         // numbers are inflated for setup
2733         verify(mListeners, times(1)).migrateToXml();
2734         verify(mConditionProviders, times(1)).migrateToXml();
2735         verify(mAssistants, times(1)).migrateToXml();
2736         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
2737     }
2738 
2739     @Test
testReadPolicyXml_readApprovedServicesFromSettings()2740     public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2741         final String preupgradeXml = "<notification-policy version=\"1\">"
2742                 + "<ranking></ranking>"
2743                 + "</notification-policy>";
2744         mService.readPolicyXml(
2745                 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2746                 false,
2747                 UserHandle.USER_ALL);
2748         verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2749         verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2750         verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
2751 
2752         // numbers are inflated for setup
2753         verify(mListeners, times(2)).migrateToXml();
2754         verify(mConditionProviders, times(2)).migrateToXml();
2755         verify(mAssistants, times(2)).migrateToXml();
2756         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
2757     }
2758 
2759     @Test
testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()2760     public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2761         final String policyXml = "<notification-policy version=\"1\">"
2762                 + "<ranking></ranking>"
2763                 + "<enabled_listeners>"
2764                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2765                 + "</enabled_listeners>"
2766                 + "<enabled_assistants>"
2767                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2768                 + "</enabled_assistants>"
2769                 + "<dnd_apps>"
2770                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2771                 + "</dnd_apps>"
2772                 + "</notification-policy>";
2773         when(mUm.isManagedProfile(10)).thenReturn(true);
2774         mService.readPolicyXml(
2775                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2776                 true,
2777                 10);
2778         verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2779         verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2780         verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2781     }
2782 
2783     @Test
testReadPolicyXml_restoresManagedServicesForNonManagedUser()2784     public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2785         final String policyXml = "<notification-policy version=\"1\">"
2786                 + "<ranking></ranking>"
2787                 + "<enabled_listeners>"
2788                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2789                 + "</enabled_listeners>"
2790                 + "<enabled_assistants>"
2791                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2792                 + "</enabled_assistants>"
2793                 + "<dnd_apps>"
2794                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2795                 + "</dnd_apps>"
2796                 + "</notification-policy>";
2797         when(mUm.isManagedProfile(10)).thenReturn(false);
2798         mService.readPolicyXml(
2799                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2800                 true,
2801                 10);
2802         verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
2803         verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
2804         verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
2805     }
2806 
2807     @Test
testLocaleChangedCallsUpdateDefaultZenModeRules()2808     public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
2809         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
2810         mService.mZenModeHelper = mZenModeHelper;
2811         mService.mLocaleChangeReceiver.onReceive(mContext,
2812                 new Intent(Intent.ACTION_LOCALE_CHANGED));
2813 
2814         verify(mZenModeHelper, times(1)).updateDefaultZenRules();
2815     }
2816 
2817     @Test
testBumpFGImportance_noChannelChangePreOApp()2818     public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
2819         String preOPkg = PKG_N_MR1;
2820         final ApplicationInfo legacy = new ApplicationInfo();
2821         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
2822         when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
2823                 .thenReturn(legacy);
2824         when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
2825                 .thenReturn(Binder.getCallingUid());
2826         getContext().setMockPackageManager(mPackageManagerClient);
2827 
2828         Notification.Builder nb = new Notification.Builder(mContext,
2829                 NotificationChannel.DEFAULT_CHANNEL_ID)
2830                 .setContentTitle("foo")
2831                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2832                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
2833                 .setPriority(Notification.PRIORITY_MIN);
2834 
2835         StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
2836                 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
2837 
2838         mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
2839                 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
2840         waitForIdle();
2841 
2842         assertEquals(IMPORTANCE_LOW,
2843                 mService.getNotificationRecord(sbn.getKey()).getImportance());
2844 
2845         nb = new Notification.Builder(mContext)
2846                 .setContentTitle("foo")
2847                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2848                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
2849                 .setPriority(Notification.PRIORITY_MIN);
2850 
2851         sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
2852                 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
2853 
2854         mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
2855                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2856         waitForIdle();
2857         assertEquals(IMPORTANCE_LOW,
2858                 mService.getNotificationRecord(sbn.getKey()).getImportance());
2859 
2860         NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
2861                 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
2862         assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
2863     }
2864 
2865     @Test
testStats_updatedOnDirectReply()2866     public void testStats_updatedOnDirectReply() throws Exception {
2867         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2868         mService.addNotification(r);
2869 
2870         mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
2871         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
2872         verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
2873     }
2874 
2875     @Test
testStats_updatedOnUserExpansion()2876     public void testStats_updatedOnUserExpansion() throws Exception {
2877         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2878         mService.addNotification(r);
2879 
2880         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
2881                 NOTIFICATION_LOCATION_UNKNOWN);
2882         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
2883         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2884 
2885         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
2886                 NOTIFICATION_LOCATION_UNKNOWN);
2887         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
2888         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2889     }
2890 
2891     @Test
testStats_notUpdatedOnAutoExpansion()2892     public void testStats_notUpdatedOnAutoExpansion() throws Exception {
2893         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2894         mService.addNotification(r);
2895 
2896         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
2897                 NOTIFICATION_LOCATION_UNKNOWN);
2898         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2899         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
2900 
2901         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
2902                 NOTIFICATION_LOCATION_UNKNOWN);
2903         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2904         verify(mAssistants).notifyAssistantExpansionChangedLocked(
2905                 eq(r.sbn), eq(false), eq((false)));
2906     }
2907 
2908     @Test
testStats_updatedOnViewSettings()2909     public void testStats_updatedOnViewSettings() throws Exception {
2910         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2911         mService.addNotification(r);
2912 
2913         mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
2914         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
2915     }
2916 
2917     @Test
testStats_updatedOnVisibilityChanged()2918     public void testStats_updatedOnVisibilityChanged() throws Exception {
2919         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2920         mService.addNotification(r);
2921 
2922         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
2923         mService.mNotificationDelegate.onNotificationVisibilityChanged(
2924                 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
2925         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2926         mService.mNotificationDelegate.onNotificationVisibilityChanged(
2927                 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
2928         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2929     }
2930 
2931     @Test
testStats_dismissalSurface()2932     public void testStats_dismissalSurface() throws Exception {
2933         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2934         mService.addNotification(r);
2935 
2936         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2937         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2938                 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2939                 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
2940         waitForIdle();
2941 
2942         assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
2943     }
2944 
2945     @Test
testStats_dismissalSentiment()2946     public void testStats_dismissalSentiment() throws Exception {
2947         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2948         mService.addNotification(r);
2949 
2950         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2951         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2952                 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2953                 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
2954         waitForIdle();
2955 
2956         assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
2957                 r.getStats().getDismissalSentiment());
2958     }
2959 
2960     @Test
testApplyAdjustmentMultiUser()2961     public void testApplyAdjustmentMultiUser() throws Exception {
2962         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2963         mService.addNotification(r);
2964         NotificationManagerService.WorkerHandler handler = mock(
2965                 NotificationManagerService.WorkerHandler.class);
2966         mService.setHandler(handler);
2967 
2968         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2969 
2970         Bundle signals = new Bundle();
2971         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2972                 USER_SENTIMENT_NEGATIVE);
2973         Adjustment adjustment = new Adjustment(
2974                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2975         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2976 
2977         waitForIdle();
2978 
2979         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2980     }
2981 
2982     @Test
testAssistantBlockingTriggersCancel()2983     public void testAssistantBlockingTriggersCancel() throws Exception {
2984         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2985         mService.addNotification(r);
2986         NotificationManagerService.WorkerHandler handler = mock(
2987                 NotificationManagerService.WorkerHandler.class);
2988         mService.setHandler(handler);
2989 
2990         Bundle signals = new Bundle();
2991         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
2992         Adjustment adjustment = new Adjustment(
2993                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2994         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
2995         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2996 
2997         waitForIdle();
2998 
2999         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3000         verify(handler, times(1)).scheduleCancelNotification(any());
3001     }
3002 
3003     @Test
testApplyEnqueuedAdjustmentFromAssistant_singleUser()3004     public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3005         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3006         mService.addEnqueuedNotification(r);
3007         NotificationManagerService.WorkerHandler handler = mock(
3008                 NotificationManagerService.WorkerHandler.class);
3009         mService.setHandler(handler);
3010         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3011 
3012         Bundle signals = new Bundle();
3013         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3014                 USER_SENTIMENT_NEGATIVE);
3015         Adjustment adjustment = new Adjustment(
3016                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3017         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3018 
3019         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3020     }
3021 
3022     @Test
testApplyEnqueuedAdjustmentFromAssistant_importance()3023     public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
3024         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3025         mService.addEnqueuedNotification(r);
3026         NotificationManagerService.WorkerHandler handler = mock(
3027                 NotificationManagerService.WorkerHandler.class);
3028         mService.setHandler(handler);
3029         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3030 
3031         Bundle signals = new Bundle();
3032         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
3033         Adjustment adjustment = new Adjustment(
3034                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3035         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3036 
3037         assertEquals(IMPORTANCE_LOW, r.getImportance());
3038     }
3039 
3040     @Test
testApplyEnqueuedAdjustmentFromAssistant_crossUser()3041     public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3042         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3043         mService.addEnqueuedNotification(r);
3044         NotificationManagerService.WorkerHandler handler = mock(
3045                 NotificationManagerService.WorkerHandler.class);
3046         mService.setHandler(handler);
3047         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3048 
3049         Bundle signals = new Bundle();
3050         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3051                 USER_SENTIMENT_NEGATIVE);
3052         Adjustment adjustment = new Adjustment(
3053                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3054         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3055 
3056         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3057 
3058         waitForIdle();
3059 
3060         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3061     }
3062 
3063     @Test
testUserSentimentChangeTriggersUpdate()3064     public void testUserSentimentChangeTriggersUpdate() throws Exception {
3065         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3066         mService.addNotification(r);
3067         NotificationManagerService.WorkerHandler handler = mock(
3068                 NotificationManagerService.WorkerHandler.class);
3069         mService.setHandler(handler);
3070         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3071 
3072         Bundle signals = new Bundle();
3073         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3074                 USER_SENTIMENT_NEGATIVE);
3075         Adjustment adjustment = new Adjustment(
3076                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3077         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3078 
3079         waitForIdle();
3080 
3081         verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3082     }
3083 
3084     @Test
testTooLateAdjustmentTriggersUpdate()3085     public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3086         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3087         mService.addNotification(r);
3088         NotificationManagerService.WorkerHandler handler = mock(
3089                 NotificationManagerService.WorkerHandler.class);
3090         mService.setHandler(handler);
3091         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3092 
3093         Bundle signals = new Bundle();
3094         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3095                 USER_SENTIMENT_NEGATIVE);
3096         Adjustment adjustment = new Adjustment(
3097                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3098         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3099 
3100         waitForIdle();
3101 
3102         verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3103     }
3104 
3105     @Test
testEnqueuedAdjustmentAppliesAdjustments()3106     public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3107         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3108         mService.addEnqueuedNotification(r);
3109         NotificationManagerService.WorkerHandler handler = mock(
3110                 NotificationManagerService.WorkerHandler.class);
3111         mService.setHandler(handler);
3112         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3113 
3114         Bundle signals = new Bundle();
3115         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3116                 USER_SENTIMENT_NEGATIVE);
3117         Adjustment adjustment = new Adjustment(
3118                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3119         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3120 
3121         assertEquals(USER_SENTIMENT_NEGATIVE,
3122                 r.getUserSentiment());
3123     }
3124 
3125     @Test
testRestore()3126     public void testRestore() throws Exception {
3127         int systemChecks = mService.countSystemChecks;
3128         mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
3129         assertEquals(1, mService.countSystemChecks - systemChecks);
3130     }
3131 
3132     @Test
testBackup()3133     public void testBackup() throws Exception {
3134         int systemChecks = mService.countSystemChecks;
3135         mBinderService.getBackupPayload(1);
3136         assertEquals(1, mService.countSystemChecks - systemChecks);
3137     }
3138 
3139     @Test
updateUriPermissions_update()3140     public void updateUriPermissions_update() throws Exception {
3141         NotificationChannel c = new NotificationChannel(
3142                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
3143         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3144         Message message1 = new Message("", 0, "");
3145         message1.setData("",
3146                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
3147         Message message2 = new Message("", 1, "");
3148         message2.setData("",
3149                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
3150 
3151         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
3152                 .setContentTitle("foo")
3153                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3154                 .setStyle(new Notification.MessagingStyle("")
3155                         .addMessage(message1)
3156                         .addMessage(message2));
3157         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3158                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
3159 
3160         // First post means we grant access to both
3161         reset(mUgm);
3162         reset(mUgmInternal);
3163         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
3164         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
3165                 UserHandle.USER_SYSTEM);
3166         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
3167                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
3168         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
3169                 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3170 
3171         Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
3172                 .setContentTitle("foo")
3173                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3174                 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
3175         NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3176                 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
3177 
3178         // Update means we drop access to first
3179         reset(mUgmInternal);
3180         mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
3181                 UserHandle.USER_SYSTEM);
3182         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3183                 eq(message1.getDataUri()), anyInt(), anyInt());
3184 
3185         // Update back means we grant access to first again
3186         reset(mUgm);
3187         mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
3188                 UserHandle.USER_SYSTEM);
3189         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
3190                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
3191 
3192         // And update to empty means we drop everything
3193         reset(mUgmInternal);
3194         mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
3195                 UserHandle.USER_SYSTEM);
3196         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
3197                 anyInt(), anyInt());
3198     }
3199 
3200     @Test
testVisitUris()3201     public void testVisitUris() throws Exception {
3202         final Uri audioContents = Uri.parse("content://com.example/audio");
3203         final Uri backgroundImage = Uri.parse("content://com.example/background");
3204 
3205         Bundle extras = new Bundle();
3206         extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3207         extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3208 
3209         Notification n = new Notification.Builder(mContext, "a")
3210                 .setContentTitle("notification with uris")
3211                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3212                 .addExtras(extras)
3213                 .build();
3214 
3215         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3216         n.visitUris(visitor);
3217         verify(visitor, times(1)).accept(eq(audioContents));
3218         verify(visitor, times(1)).accept(eq(backgroundImage));
3219     }
3220 
3221     @Test
testSetNotificationPolicy_preP_setOldFields()3222     public void testSetNotificationPolicy_preP_setOldFields() {
3223         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3224         mService.mZenModeHelper = mZenModeHelper;
3225         NotificationManager.Policy userPolicy =
3226                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3227         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3228 
3229         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3230                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3231 
3232         int expected = SUPPRESSED_EFFECT_BADGE
3233                 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3234                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3235                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3236         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3237 
3238         assertEquals(expected, actual);
3239     }
3240 
3241     @Test
testSetNotificationPolicy_preP_setNewFields()3242     public void testSetNotificationPolicy_preP_setNewFields() {
3243         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3244         mService.mZenModeHelper = mZenModeHelper;
3245         NotificationManager.Policy userPolicy =
3246                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3247         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3248 
3249         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3250                 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3251 
3252         int expected = SUPPRESSED_EFFECT_BADGE;
3253         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3254 
3255         assertEquals(expected, actual);
3256     }
3257 
3258     @Test
testSetNotificationPolicy_preP_setOldNewFields()3259     public void testSetNotificationPolicy_preP_setOldNewFields() {
3260         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3261         mService.mZenModeHelper = mZenModeHelper;
3262         NotificationManager.Policy userPolicy =
3263                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3264         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3265 
3266         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3267                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3268 
3269         int expected =
3270                 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3271         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3272 
3273         assertEquals(expected, actual);
3274     }
3275 
3276     @Test
testSetNotificationPolicy_P_setOldFields()3277     public void testSetNotificationPolicy_P_setOldFields() {
3278         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3279         mService.mZenModeHelper = mZenModeHelper;
3280         NotificationManager.Policy userPolicy =
3281                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3282         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3283 
3284         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3285                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3286 
3287         int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3288                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3289                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3290         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3291 
3292         assertEquals(expected, actual);
3293     }
3294 
3295     @Test
testSetNotificationPolicy_P_setNewFields()3296     public void testSetNotificationPolicy_P_setNewFields() {
3297         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3298         mService.mZenModeHelper = mZenModeHelper;
3299         NotificationManager.Policy userPolicy =
3300                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3301         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3302 
3303         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3304                 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3305                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3306 
3307         int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3308                 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3309                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3310         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3311 
3312         assertEquals(expected, actual);
3313     }
3314 
3315     @Test
testSetNotificationPolicy_P_setOldNewFields()3316     public void testSetNotificationPolicy_P_setOldNewFields() {
3317         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3318         mService.mZenModeHelper = mZenModeHelper;
3319         NotificationManager.Policy userPolicy =
3320                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3321         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3322 
3323         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3324                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3325 
3326         int expected =  SUPPRESSED_EFFECT_STATUS_BAR;
3327         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3328 
3329         assertEquals(expected, actual);
3330 
3331         appPolicy = new NotificationManager.Policy(0, 0, 0,
3332                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3333                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3334 
3335         expected =  SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3336                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3337         actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3338 
3339         assertEquals(expected, actual);
3340     }
3341 
3342     @Test
testVisualDifference_foreground()3343     public void testVisualDifference_foreground() {
3344         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3345                 .setContentTitle("foo");
3346         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3347                 nb1.build(), new UserHandle(mUid), null, 0);
3348         NotificationRecord r1 =
3349                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3350 
3351         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3352                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3353                 .setContentTitle("bar");
3354         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3355                 nb2.build(), new UserHandle(mUid), null, 0);
3356         NotificationRecord r2 =
3357                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3358 
3359         assertFalse(mService.isVisuallyInterruptive(r1, r2));
3360     }
3361 
3362     @Test
testVisualDifference_diffTitle()3363     public void testVisualDifference_diffTitle() {
3364         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3365                 .setContentTitle("foo");
3366         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3367                 nb1.build(), new UserHandle(mUid), null, 0);
3368         NotificationRecord r1 =
3369                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3370 
3371         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3372                 .setContentTitle("bar");
3373         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3374                 nb2.build(), new UserHandle(mUid), null, 0);
3375         NotificationRecord r2 =
3376                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3377 
3378         assertTrue(mService.isVisuallyInterruptive(r1, r2));
3379     }
3380 
3381     @Test
testVisualDifference_inboxStyle()3382     public void testVisualDifference_inboxStyle() {
3383         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3384                 .setStyle(new Notification.InboxStyle()
3385                     .addLine("line1").addLine("line2"));
3386         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3387                 nb1.build(), new UserHandle(mUid), null, 0);
3388         NotificationRecord r1 =
3389                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3390 
3391         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3392                 .setStyle(new Notification.InboxStyle()
3393                         .addLine("line1").addLine("line2_changed"));
3394         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3395                 nb2.build(), new UserHandle(mUid), null, 0);
3396         NotificationRecord r2 =
3397                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3398 
3399         assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3400 
3401         Notification.Builder nb3 = new Notification.Builder(mContext, "")
3402                 .setStyle(new Notification.InboxStyle()
3403                         .addLine("line1"));
3404         StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3405                 nb3.build(), new UserHandle(mUid), null, 0);
3406         NotificationRecord r3 =
3407                 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3408 
3409         assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3410 
3411         Notification.Builder nb4 = new Notification.Builder(mContext, "")
3412                 .setStyle(new Notification.InboxStyle()
3413                         .addLine("line1").addLine("line2").addLine("line3"));
3414         StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3415                 nb4.build(), new UserHandle(mUid), null, 0);
3416         NotificationRecord r4 =
3417                 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3418 
3419         assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3420 
3421         Notification.Builder nb5 = new Notification.Builder(mContext, "")
3422             .setContentText("not an inbox");
3423         StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3424                 nb5.build(), new UserHandle(mUid), null, 0);
3425         NotificationRecord r5 =
3426                 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3427 
3428         assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3429     }
3430 
3431     @Test
testVisualDifference_diffText()3432     public void testVisualDifference_diffText() {
3433         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3434                 .setContentText("foo");
3435         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3436                 nb1.build(), new UserHandle(mUid), null, 0);
3437         NotificationRecord r1 =
3438                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3439 
3440         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3441                 .setContentText("bar");
3442         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3443                 nb2.build(), new UserHandle(mUid), null, 0);
3444         NotificationRecord r2 =
3445                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3446 
3447         assertTrue(mService.isVisuallyInterruptive(r1, r2));
3448     }
3449 
3450     @Test
testVisualDifference_sameText()3451     public void testVisualDifference_sameText() {
3452         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3453                 .setContentText("foo");
3454         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3455                 nb1.build(), new UserHandle(mUid), null, 0);
3456         NotificationRecord r1 =
3457                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3458 
3459         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3460                 .setContentText("foo");
3461         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3462                 nb2.build(), new UserHandle(mUid), null, 0);
3463         NotificationRecord r2 =
3464                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3465 
3466         assertFalse(mService.isVisuallyInterruptive(r1, r2));
3467     }
3468 
3469     @Test
testVisualDifference_sameTextButStyled()3470     public void testVisualDifference_sameTextButStyled() {
3471         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3472                 .setContentText(Html.fromHtml("<b>foo</b>"));
3473         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3474                 nb1.build(), new UserHandle(mUid), null, 0);
3475         NotificationRecord r1 =
3476                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3477 
3478         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3479                 .setContentText(Html.fromHtml("<b>foo</b>"));
3480         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3481                 nb2.build(), new UserHandle(mUid), null, 0);
3482         NotificationRecord r2 =
3483                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3484 
3485         assertFalse(mService.isVisuallyInterruptive(r1, r2));
3486     }
3487 
3488     @Test
testVisualDifference_diffTextButStyled()3489     public void testVisualDifference_diffTextButStyled() {
3490         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3491                 .setContentText(Html.fromHtml("<b>foo</b>"));
3492         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3493                 nb1.build(), new UserHandle(mUid), null, 0);
3494         NotificationRecord r1 =
3495                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3496 
3497         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3498                 .setContentText(Html.fromHtml("<b>bar</b>"));
3499         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3500                 nb2.build(), new UserHandle(mUid), null, 0);
3501         NotificationRecord r2 =
3502                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3503 
3504         assertTrue(mService.isVisuallyInterruptive(r1, r2));
3505     }
3506 
3507     @Test
testVisualDifference_diffProgress()3508     public void testVisualDifference_diffProgress() {
3509         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3510                 .setProgress(100, 90, false);
3511         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3512                 nb1.build(), new UserHandle(mUid), null, 0);
3513         NotificationRecord r1 =
3514                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3515 
3516         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3517                 .setProgress(100, 100, false);
3518         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3519                 nb2.build(), new UserHandle(mUid), null, 0);
3520         NotificationRecord r2 =
3521                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3522 
3523         assertTrue(mService.isVisuallyInterruptive(r1, r2));
3524     }
3525 
3526     @Test
testVisualDifference_diffProgressNotDone()3527     public void testVisualDifference_diffProgressNotDone() {
3528         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3529                 .setProgress(100, 90, false);
3530         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3531                 nb1.build(), new UserHandle(mUid), null, 0);
3532         NotificationRecord r1 =
3533                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3534 
3535         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3536                 .setProgress(100, 91, false);
3537         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3538                 nb2.build(), new UserHandle(mUid), null, 0);
3539         NotificationRecord r2 =
3540                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3541 
3542         assertFalse(mService.isVisuallyInterruptive(r1, r2));
3543     }
3544 
3545     @Test
testVisualDifference_sameProgressStillDone()3546     public void testVisualDifference_sameProgressStillDone() {
3547         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3548                 .setProgress(100, 100, false);
3549         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3550                 nb1.build(), new UserHandle(mUid), null, 0);
3551         NotificationRecord r1 =
3552                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3553 
3554         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3555                 .setProgress(100, 100, false);
3556         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3557                 nb2.build(), new UserHandle(mUid), null, 0);
3558         NotificationRecord r2 =
3559                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3560 
3561         assertFalse(mService.isVisuallyInterruptive(r1, r2));
3562     }
3563 
3564     @Test
testVisualDifference_summary()3565     public void testVisualDifference_summary() {
3566         Notification.Builder nb1 = new Notification.Builder(mContext, "")
3567                 .setGroup("bananas")
3568                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3569                 .setContentText("foo");
3570         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3571                 nb1.build(), new UserHandle(mUid), null, 0);
3572         NotificationRecord r1 =
3573                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3574 
3575         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3576                 .setGroup("bananas")
3577                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3578                 .setContentText("bar");
3579         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3580                 nb2.build(), new UserHandle(mUid), null, 0);
3581         NotificationRecord r2 =
3582                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3583 
3584         assertFalse(mService.isVisuallyInterruptive(r1, r2));
3585     }
3586 
3587     @Test
testVisualDifference_summaryNewNotification()3588     public void testVisualDifference_summaryNewNotification() {
3589         Notification.Builder nb2 = new Notification.Builder(mContext, "")
3590                 .setGroup("bananas")
3591                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3592                 .setContentText("bar");
3593         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3594                 nb2.build(), new UserHandle(mUid), null, 0);
3595         NotificationRecord r2 =
3596                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3597 
3598         assertFalse(mService.isVisuallyInterruptive(null, r2));
3599     }
3600 
3601     @Test
testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()3602     public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3603         // post 2 notification from this package
3604         final NotificationRecord notif1 = generateNotificationRecord(
3605                 mTestNotificationChannel, 1, null, true);
3606         final NotificationRecord notif2 = generateNotificationRecord(
3607                 mTestNotificationChannel, 2, null, false);
3608         mService.addNotification(notif1);
3609         mService.addNotification(notif2);
3610 
3611         // on broadcast, hide the 2 notifications
3612         mService.simulatePackageSuspendBroadcast(true, PKG);
3613         ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3614         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3615         assertEquals(2, captorHide.getValue().size());
3616 
3617         // on broadcast, unhide the 2 notifications
3618         mService.simulatePackageSuspendBroadcast(false, PKG);
3619         ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3620         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3621         assertEquals(2, captorUnhide.getValue().size());
3622     }
3623 
3624     @Test
testNoNotificationsHiddenOnSuspendedPackageBroadcast()3625     public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3626         // post 2 notification from this package
3627         final NotificationRecord notif1 = generateNotificationRecord(
3628                 mTestNotificationChannel, 1, null, true);
3629         final NotificationRecord notif2 = generateNotificationRecord(
3630                 mTestNotificationChannel, 2, null, false);
3631         mService.addNotification(notif1);
3632         mService.addNotification(notif2);
3633 
3634         // on broadcast, nothing is hidden since no notifications are of package "test_package"
3635         mService.simulatePackageSuspendBroadcast(true, "test_package");
3636         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3637         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3638         assertEquals(0, captor.getValue().size());
3639     }
3640 
3641     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast()3642     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3643         // Post 2 notifications from 2 packages
3644         NotificationRecord pkgA = new NotificationRecord(mContext,
3645                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3646         mService.addNotification(pkgA);
3647         NotificationRecord pkgB = new NotificationRecord(mContext,
3648                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3649         mService.addNotification(pkgB);
3650 
3651         // on broadcast, hide one of the packages
3652         mService.simulatePackageDistractionBroadcast(
3653                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3654         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3655         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3656         assertEquals(1, captorHide.getValue().size());
3657         assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3658 
3659         // on broadcast, unhide the package
3660         mService.simulatePackageDistractionBroadcast(
3661                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3662         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3663         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3664         assertEquals(1, captorUnhide.getValue().size());
3665         assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3666     }
3667 
3668     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()3669     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3670         // Post 2 notifications from 2 packages
3671         NotificationRecord pkgA = new NotificationRecord(mContext,
3672                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3673         mService.addNotification(pkgA);
3674         NotificationRecord pkgB = new NotificationRecord(mContext,
3675                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3676         mService.addNotification(pkgB);
3677 
3678         // on broadcast, hide one of the packages
3679         mService.simulatePackageDistractionBroadcast(
3680                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3681         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3682 
3683         // should be called only once.
3684         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3685         assertEquals(2, captorHide.getValue().size());
3686         assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3687         assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3688 
3689         // on broadcast, unhide the package
3690         mService.simulatePackageDistractionBroadcast(
3691                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3692         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3693 
3694         // should be called only once.
3695         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3696         assertEquals(2, captorUnhide.getValue().size());
3697         assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3698         assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3699     }
3700 
3701     @Test
testNoNotificationsHiddenOnDistractingPackageBroadcast()3702     public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3703         // post notification from this package
3704         final NotificationRecord notif1 = generateNotificationRecord(
3705                 mTestNotificationChannel, 1, null, true);
3706         mService.addNotification(notif1);
3707 
3708         // on broadcast, nothing is hidden since no notifications are of package "test_package"
3709         mService.simulatePackageDistractionBroadcast(
3710                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3711         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3712         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3713         assertEquals(0, captor.getValue().size());
3714     }
3715 
3716     @Test
testCanUseManagedServicesLowRamNoWatchNullPkg()3717     public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3718         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3719         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3720         when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3721                 .thenReturn(new String[] {"a", "b", "c"});
3722         when(mContext.getResources()).thenReturn(mResources);
3723 
3724         assertEquals(false, mService.canUseManagedServices(null, 0, null));
3725     }
3726 
3727     @Test
testCanUseManagedServicesLowRamNoWatchValidPkg()3728     public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3729         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3730         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3731         when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3732                 .thenReturn(new String[] {"a", "b", "c"});
3733         when(mContext.getResources()).thenReturn(mResources);
3734 
3735         assertEquals(true, mService.canUseManagedServices("b", 0, null));
3736     }
3737 
3738     @Test
testCanUseManagedServicesLowRamNoWatchNoValidPkg()3739     public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3740         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3741         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3742         when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3743                 .thenReturn(new String[] {"a", "b", "c"});
3744         when(mContext.getResources()).thenReturn(mResources);
3745 
3746         assertEquals(false, mService.canUseManagedServices("d", 0, null));
3747     }
3748 
3749     @Test
testCanUseManagedServicesLowRamWatchNoValidPkg()3750     public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3751         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3752         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3753         when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3754                 .thenReturn(new String[] {"a", "b", "c"});
3755         when(mContext.getResources()).thenReturn(mResources);
3756 
3757         assertEquals(true, mService.canUseManagedServices("d", 0, null));
3758     }
3759 
3760     @Test
testCanUseManagedServicesNoLowRamNoWatchValidPkg()3761     public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3762         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3763         when(mActivityManager.isLowRamDevice()).thenReturn(false);
3764         when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3765                 .thenReturn(new String[] {"a", "b", "c"});
3766         when(mContext.getResources()).thenReturn(mResources);
3767 
3768         assertEquals(true, mService.canUseManagedServices("d", 0 , null));
3769     }
3770 
3771     @Test
testCanUseManagedServicesNoLowRamWatchValidPkg()3772     public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
3773         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3774         when(mActivityManager.isLowRamDevice()).thenReturn(false);
3775         when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3776                 .thenReturn(new String[] {"a", "b", "c"});
3777         when(mContext.getResources()).thenReturn(mResources);
3778 
3779         assertEquals(true, mService.canUseManagedServices("d", 0, null));
3780     }
3781 
3782     @Test
testCanUseManagedServices_hasPermission()3783     public void testCanUseManagedServices_hasPermission() throws Exception {
3784         when(mPackageManager.checkPermission("perm", "pkg", 0))
3785                 .thenReturn(PackageManager.PERMISSION_GRANTED);
3786 
3787         assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
3788     }
3789 
3790     @Test
testCanUseManagedServices_noPermission()3791     public void testCanUseManagedServices_noPermission() throws Exception {
3792         when(mPackageManager.checkPermission("perm", "pkg", 0))
3793                 .thenReturn(PackageManager.PERMISSION_DENIED);
3794 
3795         assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
3796     }
3797 
3798     @Test
testCanUseManagedServices_permDoesNotMatter()3799     public void testCanUseManagedServices_permDoesNotMatter() {
3800         assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
3801     }
3802 
3803     @Test
testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()3804     public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
3805         final NotificationRecord r = generateNotificationRecord(
3806                 mTestNotificationChannel, 1, null, true);
3807         r.setTextChanged(true);
3808         mService.addNotification(r);
3809 
3810         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
3811                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
3812                 new NotificationVisibility[]{});
3813 
3814         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3815     }
3816 
3817     @Test
testSetNotificationsShownFromListener_triggersInterruptionUsageStat()3818     public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
3819             throws RemoteException {
3820         final NotificationRecord r = generateNotificationRecord(
3821                 mTestNotificationChannel, 1, null, true);
3822         r.setTextChanged(true);
3823         mService.addNotification(r);
3824 
3825         mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
3826 
3827         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3828     }
3829 
3830     @Test
testMaybeRecordInterruptionLocked_doesNotRecordTwice()3831     public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
3832             throws RemoteException {
3833         final NotificationRecord r = generateNotificationRecord(
3834                 mTestNotificationChannel, 1, null, true);
3835         r.setInterruptive(true);
3836         mService.addNotification(r);
3837 
3838         mService.maybeRecordInterruptionLocked(r);
3839         mService.maybeRecordInterruptionLocked(r);
3840 
3841         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
3842                 anyString(), anyString(), anyInt());
3843     }
3844 
3845     @Test
testBubble()3846     public void testBubble() throws Exception {
3847         mBinderService.setBubblesAllowed(PKG, mUid, false);
3848         assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3849     }
3850 
3851     @Test
testUserApprovedBubblesForPackage()3852     public void testUserApprovedBubblesForPackage() throws Exception {
3853         assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3854         mBinderService.setBubblesAllowed(PKG, mUid, true);
3855         assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3856         assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3857     }
3858 
3859     @Test
testUserRejectsBubblesForPackage()3860     public void testUserRejectsBubblesForPackage() throws Exception {
3861         assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3862         mBinderService.setBubblesAllowed(PKG, mUid, false);
3863         assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3864         assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3865     }
3866 
3867     @Test
testIsCallerInstantApp_primaryUser()3868     public void testIsCallerInstantApp_primaryUser() throws Exception {
3869         ApplicationInfo info = new ApplicationInfo();
3870         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3871         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
3872         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3873 
3874         assertTrue(mService.isCallerInstantApp(45770, 0));
3875 
3876         info.privateFlags = 0;
3877         assertFalse(mService.isCallerInstantApp(575370, 0));
3878     }
3879 
3880     @Test
testIsCallerInstantApp_secondaryUser()3881     public void testIsCallerInstantApp_secondaryUser() throws Exception {
3882         ApplicationInfo info = new ApplicationInfo();
3883         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3884         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3885         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3886         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3887 
3888         assertTrue(mService.isCallerInstantApp(68638450, 10));
3889     }
3890 
3891     @Test
testIsCallerInstantApp_userAllNotification()3892     public void testIsCallerInstantApp_userAllNotification() throws Exception {
3893         ApplicationInfo info = new ApplicationInfo();
3894         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3895         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
3896                 .thenReturn(info);
3897         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3898 
3899         assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
3900 
3901         info.privateFlags = 0;
3902         assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
3903     }
3904 
3905     @Test
testResolveNotificationUid_sameApp_nonSystemUser()3906     public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
3907         ApplicationInfo info = new ApplicationInfo();
3908         info.uid = Binder.getCallingUid();
3909         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3910         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3911 
3912         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
3913 
3914         assertEquals(info.uid, actualUid);
3915     }
3916 
3917     @Test
testResolveNotificationUid_sameApp()3918     public void testResolveNotificationUid_sameApp() throws Exception {
3919         ApplicationInfo info = new ApplicationInfo();
3920         info.uid = Binder.getCallingUid();
3921         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
3922 
3923         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
3924 
3925         assertEquals(info.uid, actualUid);
3926     }
3927 
3928     @Test
testResolveNotificationUid_sameAppDiffPackage()3929     public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
3930         ApplicationInfo info = new ApplicationInfo();
3931         info.uid = Binder.getCallingUid();
3932         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
3933 
3934         int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
3935 
3936         assertEquals(info.uid, actualUid);
3937     }
3938 
3939     @Test
testResolveNotificationUid_sameAppWrongUid()3940     public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
3941         ApplicationInfo info = new ApplicationInfo();
3942         info.uid = 1356347;
3943         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
3944 
3945         try {
3946             mService.resolveNotificationUid("caller", "caller", 9, 0);
3947             fail("Incorrect uid didn't throw security exception");
3948         } catch (SecurityException e) {
3949             // yay
3950         }
3951     }
3952 
3953     @Test
testResolveNotificationUid_delegateAllowed()3954     public void testResolveNotificationUid_delegateAllowed() throws Exception {
3955         int expectedUid = 123;
3956 
3957         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3958         mService.setPreferencesHelper(mPreferencesHelper);
3959         when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
3960                 .thenReturn(true);
3961 
3962         assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
3963     }
3964 
3965     @Test
testResolveNotificationUid_androidAllowed()3966     public void testResolveNotificationUid_androidAllowed() throws Exception {
3967         int expectedUid = 123;
3968 
3969         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3970         // no delegate
3971 
3972         assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
3973     }
3974 
3975     @Test
testResolveNotificationUid_delegateNotAllowed()3976     public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
3977         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
3978         // no delegate
3979 
3980         try {
3981             mService.resolveNotificationUid("caller", "target", 9, 0);
3982             fail("Incorrect uid didn't throw security exception");
3983         } catch (SecurityException e) {
3984             // yay
3985         }
3986     }
3987 
3988     @Test
testRemoveForegroundServiceFlagFromNotification_enqueued()3989     public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
3990         Notification n = new Notification.Builder(mContext, "").build();
3991         n.flags |= FLAG_FOREGROUND_SERVICE;
3992 
3993         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3994                 n, new UserHandle(mUid), null, 0);
3995         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3996 
3997         mService.addEnqueuedNotification(r);
3998 
3999         mInternalService.removeForegroundServiceFlagFromNotification(
4000                 PKG, r.sbn.getId(), r.sbn.getUserId());
4001 
4002         waitForIdle();
4003 
4004         verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4005     }
4006 
4007     @Test
testRemoveForegroundServiceFlagFromNotification_posted()4008     public void testRemoveForegroundServiceFlagFromNotification_posted() {
4009         Notification n = new Notification.Builder(mContext, "").build();
4010         n.flags |= FLAG_FOREGROUND_SERVICE;
4011 
4012         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4013                 n, new UserHandle(mUid), null, 0);
4014         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4015 
4016         mService.addNotification(r);
4017 
4018         mInternalService.removeForegroundServiceFlagFromNotification(
4019                 PKG, r.sbn.getId(), r.sbn.getUserId());
4020 
4021         waitForIdle();
4022 
4023         ArgumentCaptor<NotificationRecord> captor =
4024                 ArgumentCaptor.forClass(NotificationRecord.class);
4025         verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4026 
4027         assertEquals(0, captor.getValue().getNotification().flags);
4028     }
4029 
4030     @Test
testAllowForegroundToasts()4031     public void testAllowForegroundToasts() throws Exception {
4032         final String testPackage = "testPackageName";
4033         assertEquals(0, mService.mToastQueue.size());
4034         mService.isSystemUid = false;
4035 
4036         // package is not suspended
4037         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4038                 .thenReturn(false);
4039 
4040         // notifications from this package are blocked by the user
4041         mService.setPreferencesHelper(mPreferencesHelper);
4042         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4043 
4044         // this app is in the foreground
4045         when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4046 
4047         // enqueue toast -> toast should still enqueue
4048         ((INotificationManager)mService.mService).enqueueToast(testPackage,
4049                 new TestableToastCallback(), 2000, 0);
4050         assertEquals(1, mService.mToastQueue.size());
4051     }
4052 
4053     @Test
testDisallowToastsFromSuspendedPackages()4054     public void testDisallowToastsFromSuspendedPackages() throws Exception {
4055         final String testPackage = "testPackageName";
4056         assertEquals(0, mService.mToastQueue.size());
4057         mService.isSystemUid = false;
4058 
4059         // package is suspended
4060         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4061                 .thenReturn(true);
4062 
4063         // notifications from this package are NOT blocked by the user
4064         mService.setPreferencesHelper(mPreferencesHelper);
4065         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4066 
4067         // enqueue toast -> no toasts enqueued
4068         ((INotificationManager)mService.mService).enqueueToast(testPackage,
4069                 new TestableToastCallback(), 2000, 0);
4070         assertEquals(0, mService.mToastQueue.size());
4071     }
4072 
4073     @Test
testDisallowToastsFromBlockedApps()4074     public void testDisallowToastsFromBlockedApps() throws Exception {
4075         final String testPackage = "testPackageName";
4076         assertEquals(0, mService.mToastQueue.size());
4077         mService.isSystemUid = false;
4078 
4079         // package is not suspended
4080         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4081                 .thenReturn(false);
4082 
4083         // notifications from this package are blocked by the user
4084         mService.setPreferencesHelper(mPreferencesHelper);
4085         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4086 
4087         // this app is NOT in the foreground
4088         when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4089 
4090         // enqueue toast -> no toasts enqueued
4091         ((INotificationManager)mService.mService).enqueueToast(testPackage,
4092                 new TestableToastCallback(), 2000, 0);
4093         assertEquals(0, mService.mToastQueue.size());
4094     }
4095 
4096     @Test
testAlwaysAllowSystemToasts()4097     public void testAlwaysAllowSystemToasts() throws Exception {
4098         final String testPackage = "testPackageName";
4099         assertEquals(0, mService.mToastQueue.size());
4100         mService.isSystemUid = true;
4101 
4102         // package is suspended
4103         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4104                 .thenReturn(true);
4105 
4106         // notifications from this package ARE blocked by the user
4107         mService.setPreferencesHelper(mPreferencesHelper);
4108         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4109 
4110         // this app is NOT in the foreground
4111         when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4112 
4113         // enqueue toast -> system toast can still be enqueued
4114         ((INotificationManager)mService.mService).enqueueToast(testPackage,
4115                 new TestableToastCallback(), 2000, 0);
4116         assertEquals(1, mService.mToastQueue.size());
4117     }
4118 
4119     @Test
testOnNotificationSmartReplySent()4120     public void testOnNotificationSmartReplySent() {
4121         final int replyIndex = 2;
4122         final String reply = "Hello";
4123         final boolean modifiedBeforeSending = true;
4124         final boolean generatedByAssistant = true;
4125 
4126         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4127         r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
4128         mService.addNotification(r);
4129 
4130         mService.mNotificationDelegate.onNotificationSmartReplySent(
4131                 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4132                 modifiedBeforeSending);
4133         verify(mAssistants).notifyAssistantSuggestedReplySent(
4134                 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4135     }
4136 
4137     @Test
testOnNotificationActionClick()4138     public void testOnNotificationActionClick() {
4139         final int actionIndex = 2;
4140         final Notification.Action action =
4141                 new Notification.Action.Builder(null, "text", null).build();
4142         final boolean generatedByAssistant = false;
4143 
4144         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4145         mService.addNotification(r);
4146 
4147         NotificationVisibility notificationVisibility =
4148                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4149         mService.mNotificationDelegate.onNotificationActionClick(
4150                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4151                 generatedByAssistant);
4152         verify(mAssistants).notifyAssistantActionClicked(
4153                 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4154     }
4155 
4156     @Test
testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()4157     public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4158         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4159         mService.addNotification(r);
4160 
4161         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4162                 NOTIFICATION_LOCATION_UNKNOWN);
4163         NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4164                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4165         };
4166         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4167                 new NotificationVisibility[0]);
4168 
4169         assertEquals(1, mService.countLogSmartSuggestionsVisible);
4170     }
4171 
4172     @Test
testLogSmartSuggestionsVisible_noTriggerOnExpand()4173     public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4174         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4175         mService.addNotification(r);
4176 
4177         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4178                 NOTIFICATION_LOCATION_UNKNOWN);
4179 
4180         assertEquals(0, mService.countLogSmartSuggestionsVisible);
4181     }
4182 
4183     @Test
testLogSmartSuggestionsVisible_noTriggerOnVisible()4184     public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4185         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4186         mService.addNotification(r);
4187 
4188         NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
4189                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4190         };
4191         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4192                 new NotificationVisibility[0]);
4193 
4194         assertEquals(0, mService.countLogSmartSuggestionsVisible);
4195     }
4196 
4197     @Test
testReportSeen_delegated()4198     public void testReportSeen_delegated() {
4199         Notification.Builder nb =
4200                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4201                         .setContentTitle("foo")
4202                         .setSmallIcon(android.R.drawable.sym_def_app_icon);
4203 
4204         StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4205                 nb.build(), new UserHandle(mUid), null, 0);
4206         NotificationRecord r =  new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4207 
4208         mService.reportSeen(r);
4209         verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4210 
4211     }
4212 
4213     @Test
testReportSeen_notDelegated()4214     public void testReportSeen_notDelegated() {
4215         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4216 
4217         mService.reportSeen(r);
4218         verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4219     }
4220 
4221     @Test
testNotificationStats_notificationError()4222     public void testNotificationStats_notificationError() {
4223         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4224         mService.addNotification(r);
4225 
4226         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4227                 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4228                 new UserHandle(mUid), null, 0);
4229         NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4230         mService.addEnqueuedNotification(update);
4231         assertNull(update.sbn.getNotification().getSmallIcon());
4232 
4233         NotificationManagerService.PostNotificationRunnable runnable =
4234                 mService.new PostNotificationRunnable(update.getKey());
4235         runnable.run();
4236         waitForIdle();
4237 
4238         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4239         verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4240         assertNotNull(captor.getValue());
4241     }
4242 
4243     @Test
testCanNotifyAsUser_crossUser()4244     public void testCanNotifyAsUser_crossUser() throws Exception {
4245         // same user no problem
4246         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4247 
4248         // cross user, no permission, problem
4249         try {
4250             mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4251             fail("Should not be callable cross user without cross user permission");
4252         } catch (SecurityException e) {
4253             // good
4254         }
4255 
4256         // cross user, with permission, no problem
4257         TestablePermissions perms = mContext.getTestablePermissions();
4258         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4259         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4260     }
4261 
4262     @Test
testgetNotificationChannels_crossUser()4263     public void testgetNotificationChannels_crossUser() throws Exception {
4264         // same user no problem
4265         mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4266 
4267         // cross user, no permission, problem
4268         try {
4269             mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4270             fail("Should not be callable cross user without cross user permission");
4271         } catch (SecurityException e) {
4272             // good
4273         }
4274 
4275         // cross user, with permission, no problem
4276         TestablePermissions perms = mContext.getTestablePermissions();
4277         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4278         mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4279     }
4280 
4281     @Test
setDefaultAssistantForUser_fromConfigXml()4282     public void setDefaultAssistantForUser_fromConfigXml() {
4283         clearDeviceConfig();
4284         ComponentName xmlConfig = new ComponentName("config", "xml");
4285         when(mResources
4286                 .getString(
4287                         com.android.internal.R.string.config_defaultAssistantAccessComponent))
4288                 .thenReturn(xmlConfig.flattenToString());
4289         when(mContext.getResources()).thenReturn(mResources);
4290         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4291                 .thenReturn(Collections.singleton(xmlConfig));
4292         mService.setNotificationAssistantAccessGrantedCallback(
4293                 mNotificationAssistantAccessGrantedCallback);
4294 
4295         mService.setDefaultAssistantForUser(0);
4296 
4297         verify(mNotificationAssistantAccessGrantedCallback)
4298                 .onGranted(eq(xmlConfig), eq(0), eq(true));
4299     }
4300 
4301     @Test
setDefaultAssistantForUser_fromDeviceConfig()4302     public void setDefaultAssistantForUser_fromDeviceConfig() {
4303         ComponentName xmlConfig = new ComponentName("xml", "config");
4304         ComponentName deviceConfig = new ComponentName("device", "config");
4305         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4306         when(mResources
4307                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4308                 .thenReturn(xmlConfig.flattenToString());
4309         when(mContext.getResources()).thenReturn(mResources);
4310         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4311                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
4312         mService.setNotificationAssistantAccessGrantedCallback(
4313                 mNotificationAssistantAccessGrantedCallback);
4314 
4315         mService.setDefaultAssistantForUser(0);
4316 
4317         verify(mNotificationAssistantAccessGrantedCallback)
4318                 .onGranted(eq(deviceConfig), eq(0), eq(true));
4319     }
4320 
4321     @Test
setDefaultAssistantForUser_deviceConfigInvalid()4322     public void setDefaultAssistantForUser_deviceConfigInvalid() {
4323         ComponentName xmlConfig = new ComponentName("xml", "config");
4324         ComponentName deviceConfig = new ComponentName("device", "config");
4325         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4326         when(mResources
4327                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4328                 .thenReturn(xmlConfig.flattenToString());
4329         when(mContext.getResources()).thenReturn(mResources);
4330         // Only xmlConfig is valid, deviceConfig is not.
4331         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4332                 .thenReturn(Collections.singleton(xmlConfig));
4333         mService.setNotificationAssistantAccessGrantedCallback(
4334                 mNotificationAssistantAccessGrantedCallback);
4335 
4336         mService.setDefaultAssistantForUser(0);
4337 
4338         verify(mNotificationAssistantAccessGrantedCallback)
4339                 .onGranted(eq(xmlConfig), eq(0), eq(true));
4340     }
4341 
4342     @Test
testFlagBubble()4343     public void testFlagBubble() throws RemoteException {
4344         // Bubbles are allowed!
4345         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4346 
4347         // Notif with bubble metadata but not our other misc requirements
4348         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4349                 null /* tvExtender */, true /* isBubble */);
4350 
4351         // Say we're foreground
4352         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4353                 IMPORTANCE_FOREGROUND);
4354 
4355         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4356                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4357         waitForIdle();
4358 
4359         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4360         assertEquals(1, notifs.length);
4361         assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4362         assertTrue(mService.getNotificationRecord(
4363                 nr.sbn.getKey()).getNotification().isBubbleNotification());
4364     }
4365 
4366     @Test
testFlagBubble_noFlag_appNotAllowed()4367     public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4368         // Bubbles are allowed!
4369         setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4370 
4371         // Notif with bubble metadata but not our other misc requirements
4372         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4373                 null /* tvExtender */, true /* isBubble */);
4374 
4375         // Say we're foreground
4376         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4377                 IMPORTANCE_FOREGROUND);
4378 
4379         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4380                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4381         waitForIdle();
4382 
4383         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4384         assertEquals(1, notifs.length);
4385         assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4386         assertFalse(mService.getNotificationRecord(
4387                 nr.sbn.getKey()).getNotification().isBubbleNotification());
4388     }
4389 
4390     @Test
testFlagBubbleNotifs_flag_appForeground()4391     public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
4392         // Bubbles are allowed!
4393         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4394 
4395         // Notif with bubble metadata but not our other misc requirements
4396         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4397                 null /* tvExtender */, true /* isBubble */);
4398 
4399         // Say we're foreground
4400         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4401                 IMPORTANCE_FOREGROUND);
4402 
4403         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4404                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4405         waitForIdle();
4406 
4407         // yes allowed, yes foreground, yes bubble
4408         assertTrue(mService.getNotificationRecord(
4409                 nr.sbn.getKey()).getNotification().isBubbleNotification());
4410     }
4411 
4412     @Test
testFlagBubbleNotifs_noFlag_appNotForeground()4413     public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4414         // Bubbles are allowed!
4415         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4416 
4417         // Notif with bubble metadata but not our other misc requirements
4418         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4419                 null /* tvExtender */, true /* isBubble */);
4420 
4421         // Make sure we're NOT foreground
4422         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4423                 IMPORTANCE_VISIBLE);
4424 
4425         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4426                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4427         waitForIdle();
4428 
4429         // yes allowed but NOT foreground, no bubble
4430         assertFalse(mService.getNotificationRecord(
4431                 nr.sbn.getKey()).getNotification().isBubbleNotification());
4432     }
4433 
4434     @Test
testFlagBubbleNotifs_flag_previousForegroundFlag()4435     public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4436         // Bubbles are allowed!
4437         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4438 
4439         // Notif with bubble metadata but not our other misc requirements
4440         NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4441                 null /* tvExtender */, true /* isBubble */);
4442 
4443         // Send notif when we're foreground
4444         when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4445                 IMPORTANCE_FOREGROUND);
4446         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4447                 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4448         waitForIdle();
4449 
4450         // yes allowed, yes foreground, yes bubble
4451         assertTrue(mService.getNotificationRecord(
4452                 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4453 
4454         // Send a new update when we're not foreground
4455         NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4456                 null /* tvExtender */, true /* isBubble */);
4457 
4458         when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4459                 IMPORTANCE_VISIBLE);
4460         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4461                 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4462         waitForIdle();
4463 
4464         // yes allowed, previously foreground / flagged, yes bubble
4465         assertTrue(mService.getNotificationRecord(
4466                 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4467 
4468         StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4469         assertEquals(1, notifs2.length);
4470         assertEquals(1, mService.getNotificationRecordCount());
4471     }
4472 
4473     @Test
testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()4474     public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4475             throws RemoteException {
4476         // Bubbles are allowed!
4477         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4478 
4479         // Notif with bubble metadata but not our other misc requirements
4480         NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4481                 null /* tvExtender */, true /* isBubble */);
4482 
4483         // Send notif when we're foreground
4484         when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4485                 IMPORTANCE_FOREGROUND);
4486         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4487                 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4488         waitForIdle();
4489 
4490         // yes allowed, yes foreground, yes bubble
4491         assertTrue(mService.getNotificationRecord(
4492                 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4493 
4494         // Remove the bubble
4495         mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(),
4496                 nr1.sbn.getUserId());
4497         waitForIdle();
4498 
4499         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4500         assertEquals(0, notifs.length);
4501         assertEquals(0, mService.getNotificationRecordCount());
4502 
4503         // Send a new update when we're not foreground
4504         NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4505                 null /* tvExtender */, true /* isBubble */);
4506 
4507         when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4508                 IMPORTANCE_VISIBLE);
4509         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4510                 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4511         waitForIdle();
4512 
4513         // yes allowed, but was removed & no foreground, so no bubble
4514         assertFalse(mService.getNotificationRecord(
4515                 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4516 
4517         StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4518         assertEquals(1, notifs2.length);
4519         assertEquals(1, mService.getNotificationRecordCount());
4520     }
4521 
4522     @Test
testFlagBubbleNotifs_flag_messaging()4523     public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4524         // Bubbles are allowed!
4525         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4526 
4527         // Give it bubble metadata
4528         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4529         // Give it a person
4530         Person person = new Person.Builder()
4531                 .setName("bubblebot")
4532                 .build();
4533         // It needs remote input to be bubble-able
4534         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4535         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4536         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4537         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4538                 inputIntent).addRemoteInput(remoteInput)
4539                 .build();
4540         // Make it messaging style
4541         Notification.Builder nb = new Notification.Builder(mContext,
4542                 mTestNotificationChannel.getId())
4543                 .setContentTitle("foo")
4544                 .setBubbleMetadata(data)
4545                 .setStyle(new Notification.MessagingStyle(person)
4546                         .setConversationTitle("Bubble Chat")
4547                         .addMessage("Hello?",
4548                                 SystemClock.currentThreadTimeMillis() - 300000, person)
4549                         .addMessage("Is it me you're looking for?",
4550                                 SystemClock.currentThreadTimeMillis(), person)
4551                 )
4552                 .setActions(replyAction)
4553                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4554 
4555         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4556                 nb.build(), new UserHandle(mUid), null, 0);
4557         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4558 
4559         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4560                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4561         waitForIdle();
4562 
4563         // yes allowed, yes messaging, yes bubble
4564         assertTrue(mService.getNotificationRecord(
4565                 sbn.getKey()).getNotification().isBubbleNotification());
4566     }
4567 
4568     @Test
testFlagBubbleNotifs_flag_phonecall()4569     public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4570         // Bubbles are allowed!
4571         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4572 
4573         // Give it bubble metadata
4574         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4575         // Give it a person
4576         Person person = new Person.Builder()
4577                 .setName("bubblebot")
4578                 .build();
4579         // Make it a phone call
4580         Notification.Builder nb = new Notification.Builder(mContext,
4581                 mTestNotificationChannel.getId())
4582                 .setCategory(CATEGORY_CALL)
4583                 .addPerson(person)
4584                 .setContentTitle("foo")
4585                 .setBubbleMetadata(data)
4586                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4587 
4588         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4589                 nb.build(), new UserHandle(mUid), null, 0);
4590         // Make sure it has foreground service
4591         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4592         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4593 
4594         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4595                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4596         waitForIdle();
4597 
4598         // yes phone call, yes person, yes foreground service, yes bubble
4599         assertTrue(mService.getNotificationRecord(
4600                 sbn.getKey()).getNotification().isBubbleNotification());
4601     }
4602 
4603     @Test
testFlagBubbleNotifs_noFlag_phonecall_noForegroundService()4604     public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4605         // Bubbles are allowed!
4606         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4607 
4608         // Give it bubble metadata
4609         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4610         // Give it a person
4611         Person person = new Person.Builder()
4612                 .setName("bubblebot")
4613                 .build();
4614         // Make it a phone call
4615         Notification.Builder nb = new Notification.Builder(mContext,
4616                 mTestNotificationChannel.getId())
4617                 .setCategory(CATEGORY_CALL)
4618                 .addPerson(person)
4619                 .setContentTitle("foo")
4620                 .setBubbleMetadata(data)
4621                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4622 
4623         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4624                 nb.build(), new UserHandle(mUid), null, 0);
4625         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4626 
4627         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4628                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4629         waitForIdle();
4630 
4631         // yes phone call, yes person, NO foreground service, no bubble
4632         assertFalse(mService.getNotificationRecord(
4633                 sbn.getKey()).getNotification().isBubbleNotification());
4634     }
4635 
4636     @Test
testFlagBubbleNotifs_noFlag_phonecall_noPerson()4637     public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4638         // Bubbles are allowed!
4639         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4640 
4641         // Give it bubble metadata
4642         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4643         // Make it a phone call
4644         Notification.Builder nb = new Notification.Builder(mContext,
4645                 mTestNotificationChannel.getId())
4646                 .setCategory(CATEGORY_CALL)
4647                 .setContentTitle("foo")
4648                 .setBubbleMetadata(data)
4649                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4650 
4651         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4652                 nb.build(), new UserHandle(mUid), null, 0);
4653         // Make sure it has foreground service
4654         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4655         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4656 
4657         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4658                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4659         waitForIdle();
4660 
4661         // yes phone call, yes foreground service, BUT NO person, no bubble
4662         assertFalse(mService.getNotificationRecord(
4663                 sbn.getKey()).getNotification().isBubbleNotification());
4664     }
4665 
4666     @Test
testFlagBubbleNotifs_noFlag_phonecall_noCategory()4667     public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4668         // Bubbles are allowed!
4669         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4670 
4671         // Give it bubble metadata
4672         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4673         // Give it a person
4674         Person person = new Person.Builder()
4675                 .setName("bubblebot")
4676                 .build();
4677         // No category
4678         Notification.Builder nb = new Notification.Builder(mContext,
4679                 mTestNotificationChannel.getId())
4680                 .addPerson(person)
4681                 .setContentTitle("foo")
4682                 .setBubbleMetadata(data)
4683                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4684 
4685         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4686                 nb.build(), new UserHandle(mUid), null, 0);
4687         // Make sure it has foreground service
4688         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4689         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4690 
4691         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4692                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4693         waitForIdle();
4694 
4695         // yes person, yes foreground service, BUT NO call, no bubble
4696         assertFalse(mService.getNotificationRecord(
4697                 sbn.getKey()).getNotification().isBubbleNotification());
4698     }
4699 
4700     @Test
testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()4701     public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
4702         // Bubbles are NOT allowed!
4703         setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
4704 
4705         // Give it bubble metadata
4706         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4707         // Give it a person
4708         Person person = new Person.Builder()
4709                 .setName("bubblebot")
4710                 .build();
4711         // Make it messaging style
4712         Notification.Builder nb = new Notification.Builder(mContext,
4713                 mTestNotificationChannel.getId())
4714                 .setContentTitle("foo")
4715                 .setBubbleMetadata(data)
4716                 .setStyle(new Notification.MessagingStyle(person)
4717                         .setConversationTitle("Bubble Chat")
4718                         .addMessage("Hello?",
4719                                 SystemClock.currentThreadTimeMillis() - 300000, person)
4720                         .addMessage("Is it me you're looking for?",
4721                                 SystemClock.currentThreadTimeMillis(), person)
4722                 )
4723                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4724 
4725         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4726                 nb.build(), new UserHandle(mUid), null, 0);
4727         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4728 
4729         // Post the notification
4730         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4731                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4732         waitForIdle();
4733 
4734         // not allowed, no bubble
4735         assertFalse(mService.getNotificationRecord(
4736                 sbn.getKey()).getNotification().isBubbleNotification());
4737     }
4738 
4739     @Test
testFlagBubbleNotifs_noFlag_notBubble()4740     public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
4741         // Bubbles are allowed!
4742         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
4743 
4744         // Notif WITHOUT bubble metadata
4745         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4746 
4747         // Post the notification
4748         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4749                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4750         waitForIdle();
4751 
4752         // no bubble metadata, no bubble
4753         assertFalse(mService.getNotificationRecord(
4754                 nr.sbn.getKey()).getNotification().isBubbleNotification());
4755     }
4756 
4757     @Test
testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()4758     public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
4759         // Bubbles are allowed except on this channel
4760         setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
4761 
4762         // Give it bubble metadata
4763         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4764         // Give it a person
4765         Person person = new Person.Builder()
4766                 .setName("bubblebot")
4767                 .build();
4768         // Make it messaging style
4769         Notification.Builder nb = new Notification.Builder(mContext,
4770                 mTestNotificationChannel.getId())
4771                 .setContentTitle("foo")
4772                 .setBubbleMetadata(data)
4773                 .setStyle(new Notification.MessagingStyle(person)
4774                         .setConversationTitle("Bubble Chat")
4775                         .addMessage("Hello?",
4776                                 SystemClock.currentThreadTimeMillis() - 300000, person)
4777                         .addMessage("Is it me you're looking for?",
4778                                 SystemClock.currentThreadTimeMillis(), person)
4779                 )
4780                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4781 
4782         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4783                 nb.build(), new UserHandle(mUid), null, 0);
4784         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4785 
4786         // Post the notification
4787         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4788                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4789         waitForIdle();
4790 
4791         // channel not allowed, no bubble
4792         assertFalse(mService.getNotificationRecord(
4793                 sbn.getKey()).getNotification().isBubbleNotification());
4794     }
4795 
4796     @Test
testFlagBubbleNotifs_noFlag_phonecall_notAllowed()4797     public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
4798         // Bubbles are not allowed!
4799         setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
4800 
4801         // Give it bubble metadata
4802         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4803         // Give it a person
4804         Person person = new Person.Builder()
4805                 .setName("bubblebot")
4806                 .build();
4807         // Make it a phone call
4808         Notification.Builder nb = new Notification.Builder(mContext,
4809                 mTestNotificationChannel.getId())
4810                 .setCategory(CATEGORY_CALL)
4811                 .addPerson(person)
4812                 .setContentTitle("foo")
4813                 .setBubbleMetadata(data)
4814                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4815 
4816         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4817                 nb.build(), new UserHandle(mUid), null, 0);
4818         // Make sure it has foreground service
4819         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4820         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4821 
4822         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4823                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4824         waitForIdle();
4825 
4826         // yes phone call, yes person, yes foreground service, but not allowed, no bubble
4827         assertFalse(mService.getNotificationRecord(
4828                 sbn.getKey()).getNotification().isBubbleNotification());
4829     }
4830 
4831     @Test
testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed()4832     public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
4833         // Bubbles are allowed, but not on channel.
4834         setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
4835 
4836         // Give it bubble metadata
4837         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4838         // Give it a person
4839         Person person = new Person.Builder()
4840                 .setName("bubblebot")
4841                 .build();
4842         // Make it a phone call
4843         Notification.Builder nb = new Notification.Builder(mContext,
4844                 mTestNotificationChannel.getId())
4845                 .setCategory(CATEGORY_CALL)
4846                 .addPerson(person)
4847                 .setContentTitle("foo")
4848                 .setBubbleMetadata(data)
4849                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4850 
4851         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4852                 nb.build(), new UserHandle(mUid), null, 0);
4853         // Make sure it has foreground service
4854         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4855         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4856 
4857         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4858                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4859         waitForIdle();
4860 
4861         // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
4862         assertFalse(mService.getNotificationRecord(
4863                 sbn.getKey()).getNotification().isBubbleNotification());
4864     }
4865 
4866     @Test
testCancelAllNotifications_cancelsBubble()4867     public void testCancelAllNotifications_cancelsBubble() throws Exception {
4868         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4869         nr.sbn.getNotification().flags |= FLAG_BUBBLE;
4870         mService.addNotification(nr);
4871 
4872         mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
4873         waitForIdle();
4874 
4875         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4876         assertEquals(0, notifs.length);
4877         assertEquals(0, mService.getNotificationRecordCount());
4878     }
4879 
4880     @Test
testAppCancelNotifications_cancelsBubbles()4881     public void testAppCancelNotifications_cancelsBubbles() throws Exception {
4882         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4883         nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4884 
4885         // Post the notification
4886         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4887                 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
4888         waitForIdle();
4889 
4890         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4891         assertEquals(1, notifs.length);
4892         assertEquals(1, mService.getNotificationRecordCount());
4893 
4894         mBinderService.cancelNotificationWithTag(PKG, null, nrBubble.sbn.getId(),
4895                 nrBubble.sbn.getUserId());
4896         waitForIdle();
4897 
4898         StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4899         assertEquals(0, notifs2.length);
4900         assertEquals(0, mService.getNotificationRecordCount());
4901     }
4902 
4903     @Test
testCancelAllNotificationsFromListener_ignoresBubbles()4904     public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
4905         final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4906         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4907         nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4908 
4909         mService.addNotification(nrNormal);
4910         mService.addNotification(nrBubble);
4911 
4912         mService.getBinderService().cancelNotificationsFromListener(null, null);
4913         waitForIdle();
4914 
4915         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4916         assertEquals(1, notifs.length);
4917         assertEquals(1, mService.getNotificationRecordCount());
4918     }
4919 
4920     @Test
testCancelNotificationsFromListener_ignoresBubbles()4921     public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
4922         final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4923         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4924         nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4925 
4926         mService.addNotification(nrNormal);
4927         mService.addNotification(nrBubble);
4928 
4929         String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
4930         mService.getBinderService().cancelNotificationsFromListener(null, keys);
4931         waitForIdle();
4932 
4933         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4934         assertEquals(1, notifs.length);
4935         assertEquals(1, mService.getNotificationRecordCount());
4936     }
4937 
4938     @Test
testGetAllowedAssistantAdjustments()4939     public void testGetAllowedAssistantAdjustments() throws Exception {
4940         List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
4941         assertNotNull(capabilities);
4942 
4943         for (int i = capabilities.size() - 1; i >= 0; i--) {
4944             String capability = capabilities.get(i);
4945             mBinderService.disallowAssistantAdjustment(capability);
4946             assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
4947             List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
4948             assertNotNull(currentCapabilities);
4949             assertFalse(currentCapabilities.contains(capability));
4950         }
4951     }
4952 
4953     @Test
testAdjustRestrictedKey()4954     public void testAdjustRestrictedKey() throws Exception {
4955         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4956         mService.addNotification(r);
4957         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
4958 
4959         when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
4960         when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
4961 
4962         Bundle signals = new Bundle();
4963         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
4964         signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
4965         Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
4966                "", r.getUser().getIdentifier());
4967 
4968         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
4969         r.applyAdjustments();
4970 
4971         assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
4972         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
4973     }
4974 
4975     @Test
testAutomaticZenRuleValidation_policyFilterAgreement()4976     public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
4977         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
4978                 .thenReturn(true);
4979         mService.setZenHelper(mock(ZenModeHelper.class));
4980         ComponentName owner = new ComponentName(mContext, this.getClass());
4981         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
4982         boolean isEnabled = true;
4983         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4984                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4985 
4986         try {
4987             mBinderService.addAutomaticZenRule(rule);
4988             fail("Zen policy only applies to priority only mode");
4989         } catch (IllegalArgumentException e) {
4990             // yay
4991         }
4992 
4993         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4994                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
4995         mBinderService.addAutomaticZenRule(rule);
4996 
4997         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4998                 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4999         mBinderService.addAutomaticZenRule(rule);
5000     }
5001 
5002     @Test
testAreNotificationsEnabledForPackage_crossUser()5003     public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5004         try {
5005             mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5006                     mUid + UserHandle.PER_USER_RANGE);
5007             fail("Cannot call cross user without permission");
5008         } catch (SecurityException e) {
5009             // pass
5010         }
5011 
5012         // cross user, with permission, no problem
5013         TestablePermissions perms = mContext.getTestablePermissions();
5014         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5015         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5016                 mUid + UserHandle.PER_USER_RANGE);
5017     }
5018 
5019     @Test
testAreBubblesAllowedForPackage_crossUser()5020     public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5021         try {
5022             mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5023                     mUid + UserHandle.PER_USER_RANGE);
5024             fail("Cannot call cross user without permission");
5025         } catch (SecurityException e) {
5026             // pass
5027         }
5028 
5029         // cross user, with permission, no problem
5030         TestablePermissions perms = mContext.getTestablePermissions();
5031         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5032         mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5033                 mUid + UserHandle.PER_USER_RANGE);
5034     }
5035 
5036     @Test
testNotificationBubbleChanged_false()5037     public void testNotificationBubbleChanged_false() throws Exception {
5038         // Bubbles are allowed!
5039         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5040 
5041         // Notif with bubble metadata but not our other misc requirements
5042         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5043                 null /* tvExtender */, true /* isBubble */);
5044 
5045         // Say we're foreground
5046         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5047                 IMPORTANCE_FOREGROUND);
5048 
5049         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5050                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5051         waitForIdle();
5052 
5053         // Reset as this is called when the notif is first sent
5054         reset(mListeners);
5055 
5056         // First we were a bubble
5057         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5058         assertEquals(1, notifsBefore.length);
5059         assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5060 
5061         // Notify we're not a bubble
5062         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5063         waitForIdle();
5064 
5065         // Make sure we are not a bubble
5066         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5067         assertEquals(1, notifsAfter.length);
5068         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5069     }
5070 
5071     @Test
testNotificationBubbleChanged_true()5072     public void testNotificationBubbleChanged_true() throws Exception {
5073         // Bubbles are allowed!
5074         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5075 
5076         // Plain notification that has bubble metadata
5077         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5078                 null /* tvExtender */, true /* isBubble */);
5079         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5080                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5081         waitForIdle();
5082 
5083         // Would be a normal notification because wouldn't have met requirements to bubble
5084         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5085         assertEquals(1, notifsBefore.length);
5086         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5087 
5088         // Make the package foreground so that we're allowed to be a bubble
5089         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5090                 IMPORTANCE_FOREGROUND);
5091 
5092         // Reset as this is called when the notif is first sent
5093         reset(mListeners);
5094 
5095         // Notify we are now a bubble
5096         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5097         waitForIdle();
5098 
5099         // Make sure we are a bubble
5100         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5101         assertEquals(1, notifsAfter.length);
5102         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
5103     }
5104 
5105     @Test
testNotificationBubbleChanged_true_notAllowed()5106     public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5107         // Bubbles are allowed!
5108         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5109 
5110         // Notif that is not a bubble
5111         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5112                 null /* tvExtender */, true /* isBubble */);
5113         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5114                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5115         waitForIdle();
5116 
5117         // Reset as this is called when the notif is first sent
5118         reset(mListeners);
5119 
5120         // Would be a normal notification because wouldn't have met requirements to bubble
5121         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5122         assertEquals(1, notifsBefore.length);
5123         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5124 
5125         // Notify we are now a bubble
5126         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5127         waitForIdle();
5128 
5129         // We still wouldn't be a bubble because the notification didn't meet requirements
5130         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5131         assertEquals(1, notifsAfter.length);
5132         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5133     }
5134 
5135     @Test
testNotificationBubbles_disabled_lowRamDevice()5136     public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5137         // Bubbles are allowed!
5138         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5139 
5140         // Plain notification that has bubble metadata
5141         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5142                 null /* tvExtender */, true /* isBubble */);
5143         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5144                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5145         waitForIdle();
5146 
5147         // Would be a normal notification because wouldn't have met requirements to bubble
5148         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5149         assertEquals(1, notifsBefore.length);
5150         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5151 
5152         // Make the package foreground so that we're allowed to be a bubble
5153         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5154                 IMPORTANCE_FOREGROUND);
5155 
5156         // And we are low ram
5157         when(mActivityManager.isLowRamDevice()).thenReturn(true);
5158 
5159         // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5160         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5161         assertEquals(1, notifsAfter.length);
5162         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5163     }
5164 
5165     @Test
testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()5166     public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
5167             throws Exception {
5168         // Bubbles are allowed!
5169         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5170 
5171         // Give it bubble metadata
5172         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5173                 .setSuppressNotification(true)
5174                 .setAutoExpandBubble(true).build();
5175         // Give it a person
5176         Person person = new Person.Builder()
5177                 .setName("bubblebot")
5178                 .build();
5179         // It needs remote input to be bubble-able
5180         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5181         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5182         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5183         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5184                 inputIntent).addRemoteInput(remoteInput)
5185                 .build();
5186         // Make it messaging style
5187         Notification.Builder nb = new Notification.Builder(mContext,
5188                 mTestNotificationChannel.getId())
5189                 .setContentTitle("foo")
5190                 .setBubbleMetadata(data)
5191                 .setStyle(new Notification.MessagingStyle(person)
5192                         .setConversationTitle("Bubble Chat")
5193                         .addMessage("Hello?",
5194                                 SystemClock.currentThreadTimeMillis() - 300000, person)
5195                         .addMessage("Is it me you're looking for?",
5196                                 SystemClock.currentThreadTimeMillis(), person)
5197                 )
5198                 .setActions(replyAction)
5199                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5200 
5201         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5202                 nb.build(), new UserHandle(mUid), null, 0);
5203         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5204 
5205         // Ensure we're not foreground
5206         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5207                 IMPORTANCE_VISIBLE);
5208 
5209         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5210                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5211         waitForIdle();
5212 
5213         // yes allowed, yes messaging, yes bubble
5214         Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5215         assertTrue(notif.isBubbleNotification());
5216 
5217         // Our flags should have failed since we're not foreground
5218         assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
5219         assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
5220     }
5221 
5222     @Test
testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()5223     public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
5224             throws RemoteException {
5225         // Bubbles are allowed!
5226         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5227 
5228         // Give it bubble metadata
5229         Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5230                 .setSuppressNotification(true)
5231                 .setAutoExpandBubble(true).build();
5232         // Give it a person
5233         Person person = new Person.Builder()
5234                 .setName("bubblebot")
5235                 .build();
5236         // It needs remote input to be bubble-able
5237         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5238         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5239         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5240         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5241                 inputIntent).addRemoteInput(remoteInput)
5242                 .build();
5243         // Make it messaging style
5244         Notification.Builder nb = new Notification.Builder(mContext,
5245                 mTestNotificationChannel.getId())
5246                 .setContentTitle("foo")
5247                 .setBubbleMetadata(data)
5248                 .setStyle(new Notification.MessagingStyle(person)
5249                         .setConversationTitle("Bubble Chat")
5250                         .addMessage("Hello?",
5251                                 SystemClock.currentThreadTimeMillis() - 300000, person)
5252                         .addMessage("Is it me you're looking for?",
5253                                 SystemClock.currentThreadTimeMillis(), person)
5254                 )
5255                 .setActions(replyAction)
5256                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5257 
5258         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5259                 nb.build(), new UserHandle(mUid), null, 0);
5260         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5261 
5262         // Ensure we are in the foreground
5263         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5264                 IMPORTANCE_FOREGROUND);
5265 
5266         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5267                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5268         waitForIdle();
5269 
5270         // yes allowed, yes messaging, yes bubble
5271         Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5272         assertTrue(notif.isBubbleNotification());
5273 
5274         // Our flags should have failed since we are foreground
5275         assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
5276         assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
5277     }
5278 
5279     @Test
testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()5280     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
5281             throws Exception {
5282         // Bubbles are allowed!
5283         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5284 
5285         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5286                 true /* summaryAutoCancel */);
5287 
5288         // Dismiss summary
5289         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5290                 true);
5291         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(),
5292                 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(),
5293                 NotificationStats.DISMISSAL_SHADE,
5294                 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
5295         waitForIdle();
5296 
5297         // The bubble should still exist
5298         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5299         assertEquals(1, notifsAfter.length);
5300     }
5301 
5302     @Test
testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()5303     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
5304             throws Exception {
5305         // Bubbles are allowed!
5306         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5307 
5308         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5309                 true /* summaryAutoCancel */);
5310 
5311         // Click summary
5312         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5313                 true);
5314         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
5315                 nrSummary.getKey(), nv);
5316         waitForIdle();
5317 
5318         // The bubble should still exist
5319         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5320         assertEquals(1, notifsAfter.length);
5321     }
5322 }
5323