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