• 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_VISIBLE;
21 import static android.app.Notification.FLAG_AUTO_CANCEL;
22 import static android.app.Notification.FLAG_BUBBLE;
23 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
24 import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
25 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
26 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
27 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
28 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
29 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
30 import static android.app.NotificationManager.IMPORTANCE_HIGH;
31 import static android.app.NotificationManager.IMPORTANCE_LOW;
32 import static android.app.NotificationManager.IMPORTANCE_MAX;
33 import static android.app.NotificationManager.IMPORTANCE_NONE;
34 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
35 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
36 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
37 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
38 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
39 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
40 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
41 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
42 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
43 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
44 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
45 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
46 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
47 import static android.content.pm.PackageManager.FEATURE_WATCH;
48 import static android.content.pm.PackageManager.PERMISSION_DENIED;
49 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
50 import static android.os.Build.VERSION_CODES.O_MR1;
51 import static android.os.Build.VERSION_CODES.P;
52 import static android.os.UserHandle.USER_SYSTEM;
53 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
54 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
55 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
56 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
57 
58 import static junit.framework.Assert.assertEquals;
59 import static junit.framework.Assert.assertFalse;
60 import static junit.framework.Assert.assertNotNull;
61 import static junit.framework.Assert.assertNull;
62 import static junit.framework.Assert.assertTrue;
63 import static junit.framework.Assert.fail;
64 
65 import static org.mockito.ArgumentMatchers.isNull;
66 import static org.mockito.Matchers.anyBoolean;
67 import static org.mockito.Matchers.anyLong;
68 import static org.mockito.Matchers.anyString;
69 import static org.mockito.Matchers.eq;
70 import static org.mockito.Mockito.any;
71 import static org.mockito.Mockito.anyInt;
72 import static org.mockito.Mockito.clearInvocations;
73 import static org.mockito.Mockito.doAnswer;
74 import static org.mockito.Mockito.doNothing;
75 import static org.mockito.Mockito.doThrow;
76 import static org.mockito.Mockito.mock;
77 import static org.mockito.Mockito.never;
78 import static org.mockito.Mockito.reset;
79 import static org.mockito.Mockito.spy;
80 import static org.mockito.Mockito.timeout;
81 import static org.mockito.Mockito.times;
82 import static org.mockito.Mockito.verify;
83 import static org.mockito.Mockito.when;
84 
85 import android.app.ActivityManager;
86 import android.app.ActivityManagerInternal;
87 import android.app.AlarmManager;
88 import android.app.AppOpsManager;
89 import android.app.AutomaticZenRule;
90 import android.app.IActivityManager;
91 import android.app.INotificationManager;
92 import android.app.ITransientNotification;
93 import android.app.IUriGrantsManager;
94 import android.app.Notification;
95 import android.app.Notification.MessagingStyle.Message;
96 import android.app.NotificationChannel;
97 import android.app.NotificationChannelGroup;
98 import android.app.NotificationManager;
99 import android.app.PendingIntent;
100 import android.app.Person;
101 import android.app.RemoteInput;
102 import android.app.StatsManager;
103 import android.app.admin.DevicePolicyManagerInternal;
104 import android.app.usage.UsageStatsManagerInternal;
105 import android.companion.ICompanionDeviceManager;
106 import android.content.ComponentName;
107 import android.content.ContentUris;
108 import android.content.Context;
109 import android.content.Intent;
110 import android.content.pm.ActivityInfo;
111 import android.content.pm.ApplicationInfo;
112 import android.content.pm.IPackageManager;
113 import android.content.pm.LauncherApps;
114 import android.content.pm.PackageManager;
115 import android.content.pm.PackageManagerInternal;
116 import android.content.pm.ParceledListSlice;
117 import android.content.pm.ShortcutInfo;
118 import android.content.pm.ShortcutServiceInternal;
119 import android.content.pm.UserInfo;
120 import android.content.res.Resources;
121 import android.graphics.Color;
122 import android.graphics.drawable.Icon;
123 import android.media.AudioManager;
124 import android.net.Uri;
125 import android.os.Binder;
126 import android.os.Build;
127 import android.os.Bundle;
128 import android.os.IBinder;
129 import android.os.Parcel;
130 import android.os.Process;
131 import android.os.RemoteException;
132 import android.os.SystemClock;
133 import android.os.UserHandle;
134 import android.os.UserManager;
135 import android.provider.DeviceConfig;
136 import android.provider.MediaStore;
137 import android.provider.Settings;
138 import android.service.notification.Adjustment;
139 import android.service.notification.ConversationChannelWrapper;
140 import android.service.notification.NotificationListenerService;
141 import android.service.notification.NotificationStats;
142 import android.service.notification.StatusBarNotification;
143 import android.service.notification.ZenPolicy;
144 import android.telephony.TelephonyManager;
145 import android.test.suitebuilder.annotation.SmallTest;
146 import android.testing.AndroidTestingRunner;
147 import android.testing.TestableContext;
148 import android.testing.TestableLooper;
149 import android.testing.TestableLooper.RunWithLooper;
150 import android.testing.TestablePermissions;
151 import android.testing.TestableResources;
152 import android.text.Html;
153 import android.text.TextUtils;
154 import android.util.ArrayMap;
155 import android.util.ArraySet;
156 import android.util.AtomicFile;
157 import android.util.Xml;
158 import android.widget.RemoteViews;
159 
160 import androidx.annotation.Nullable;
161 import androidx.test.InstrumentationRegistry;
162 
163 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
164 import com.android.internal.logging.InstanceIdSequence;
165 import com.android.internal.logging.InstanceIdSequenceFake;
166 import com.android.internal.statusbar.NotificationVisibility;
167 import com.android.internal.util.FastXmlSerializer;
168 import com.android.server.DeviceIdleInternal;
169 import com.android.server.LocalServices;
170 import com.android.server.SystemService;
171 import com.android.server.UiServiceTestCase;
172 import com.android.server.lights.LightsManager;
173 import com.android.server.lights.LogicalLight;
174 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
175 import com.android.server.notification.NotificationManagerService.NotificationListeners;
176 import com.android.server.pm.PackageManagerService;
177 import com.android.server.statusbar.StatusBarManagerInternal;
178 import com.android.server.uri.UriGrantsManagerInternal;
179 import com.android.server.wm.ActivityTaskManagerInternal;
180 import com.android.server.wm.WindowManagerInternal;
181 
182 import org.junit.After;
183 import org.junit.Before;
184 import org.junit.Test;
185 import org.junit.runner.RunWith;
186 import org.mockito.ArgumentCaptor;
187 import org.mockito.Mock;
188 import org.mockito.MockitoAnnotations;
189 import org.mockito.stubbing.Answer;
190 import org.xmlpull.v1.XmlPullParser;
191 import org.xmlpull.v1.XmlSerializer;
192 
193 import java.io.BufferedInputStream;
194 import java.io.BufferedOutputStream;
195 import java.io.ByteArrayInputStream;
196 import java.io.ByteArrayOutputStream;
197 import java.io.File;
198 import java.io.FileOutputStream;
199 import java.util.ArrayList;
200 import java.util.Arrays;
201 import java.util.Collections;
202 import java.util.List;
203 import java.util.Map;
204 import java.util.Set;
205 import java.util.function.Consumer;
206 
207 
208 @SmallTest
209 @RunWith(AndroidTestingRunner.class)
210 @RunWithLooper
211 public class NotificationManagerServiceTest extends UiServiceTestCase {
212     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
213 
214     private final int mUid = Binder.getCallingUid();
215     private TestableNotificationManagerService mService;
216     private INotificationManager mBinderService;
217     private NotificationManagerInternal mInternalService;
218     private ShortcutHelper mShortcutHelper;
219     @Mock
220     private IPackageManager mPackageManager;
221     @Mock
222     private PackageManager mPackageManagerClient;
223     @Mock
224     private WindowManagerInternal mWindowManagerInternal;
225     private TestableContext mContext = spy(getContext());
226     private final String PKG = mContext.getPackageName();
227     private TestableLooper mTestableLooper;
228     @Mock
229     private RankingHelper mRankingHelper;
230     @Mock private PreferencesHelper mPreferencesHelper;
231     AtomicFile mPolicyFile;
232     File mFile;
233     @Mock
234     private NotificationUsageStats mUsageStats;
235     @Mock
236     private UsageStatsManagerInternal mAppUsageStats;
237     @Mock
238     private AudioManager mAudioManager;
239     @Mock
240     private LauncherApps mLauncherApps;
241     @Mock
242     private ShortcutServiceInternal mShortcutServiceInternal;
243     @Mock
244     ActivityManager mActivityManager;
245     @Mock
246     Resources mResources;
247     @Mock
248     RankingHandler mRankingHandler;
249     @Mock
250     protected PackageManagerInternal mPackageManagerInternal;
251 
252     private static final int MAX_POST_DELAY = 1000;
253 
254     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
255             TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
256 
257     private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
258 
259     private static final String VALID_CONVO_SHORTCUT_ID = "shortcut";
260 
261     @Mock
262     private NotificationListeners mListeners;
263     @Mock private NotificationAssistants mAssistants;
264     @Mock private ConditionProviders mConditionProviders;
265     private ManagedServices.ManagedServiceInfo mListener;
266     @Mock private ICompanionDeviceManager mCompanionMgr;
267     @Mock SnoozeHelper mSnoozeHelper;
268     @Mock GroupHelper mGroupHelper;
269     @Mock
270     IBinder mPermOwner;
271     @Mock
272     IActivityManager mAm;
273     @Mock
274     ActivityTaskManagerInternal mAtm;
275     @Mock
276     IUriGrantsManager mUgm;
277     @Mock
278     UriGrantsManagerInternal mUgmInternal;
279     @Mock
280     AppOpsManager mAppOpsManager;
281     @Mock
282     private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
283             mNotificationAssistantAccessGrantedCallback;
284     @Mock
285     UserManager mUm;
286     @Mock
287     NotificationHistoryManager mHistoryManager;
288     @Mock
289     StatsManager mStatsManager;
290     @Mock
291     AlarmManager mAlarmManager;
292     NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
293     private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
294             1 << 30);
295     @Mock
296     StatusBarManagerInternal mStatusBar;
297     private final FakeSystemClock mSystemClock = new FakeSystemClock();
298 
299     // Use a Testable subclass so we can simulate calls from the system without failing.
300     private static class TestableNotificationManagerService extends NotificationManagerService {
301         int countSystemChecks = 0;
302         boolean isSystemUid = true;
303         int countLogSmartSuggestionsVisible = 0;
304         // If true, don't enqueue the PostNotificationRunnables, just trap them
305         boolean trapEnqueuedNotifications = false;
306         final ArrayList<NotificationManagerService.PostNotificationRunnable> trappedRunnables =
307                 new ArrayList<>();
308         @Nullable
309         NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
310 
TestableNotificationManagerService( Context context, NotificationRecordLogger logger, InjectableSystemClock systemClock, InstanceIdSequence notificationInstanceIdSequence)311         TestableNotificationManagerService(
312                 Context context,
313                 NotificationRecordLogger logger,
314                 InjectableSystemClock systemClock,
315                 InstanceIdSequence notificationInstanceIdSequence) {
316             super(context, logger, systemClock, notificationInstanceIdSequence);
317         }
318 
getRankingHelper()319         RankingHelper getRankingHelper() {
320             return mRankingHelper;
321         }
322 
323         @Override
isCallingUidSystem()324         protected boolean isCallingUidSystem() {
325             countSystemChecks++;
326             return isSystemUid;
327         }
328 
329         @Override
isCallerSystemOrPhone()330         protected boolean isCallerSystemOrPhone() {
331             countSystemChecks++;
332             return isSystemUid;
333         }
334 
335         @Override
getCompanionManager()336         protected ICompanionDeviceManager getCompanionManager() {
337             return null;
338         }
339 
340         @Override
reportUserInteraction(NotificationRecord r)341         protected void reportUserInteraction(NotificationRecord r) {
342             return;
343         }
344 
345         @Override
handleSavePolicyFile()346         protected void handleSavePolicyFile() {
347             return;
348         }
349 
350         @Override
logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation)351         void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
352             super.logSmartSuggestionsVisible(r, notificationLocation);
353             countLogSmartSuggestionsVisible++;
354         }
355 
356         @Override
setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int userId, boolean granted)357         protected void setNotificationAssistantAccessGrantedForUserInternal(
358                 ComponentName assistant, int userId, boolean granted) {
359             if (mNotificationAssistantAccessGrantedCallback != null) {
360                 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
361                 return;
362             }
363             super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
364         }
365 
366         @Override
getStringArrayResource(int key)367         protected String[] getStringArrayResource(int key) {
368             return new String[] {PKG_O};
369         }
370 
371         @Override
postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record, PostNotificationRunnable runnable)372         protected void postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record,
373                 PostNotificationRunnable runnable) {
374             if (trapEnqueuedNotifications) {
375                 trappedRunnables.add(runnable);
376                 return;
377             }
378 
379             super.postPostNotificationRunnableMaybeDelayedLocked(record, runnable);
380         }
381 
drainTrappedRunnableQueue()382         void drainTrappedRunnableQueue() {
383             for (Runnable r : trappedRunnables) {
384                 getWorkHandler().post(r);
385             }
386         }
387 
setNotificationAssistantAccessGrantedCallback( @ullable NotificationAssistantAccessGrantedCallback callback)388         private void setNotificationAssistantAccessGrantedCallback(
389                 @Nullable NotificationAssistantAccessGrantedCallback callback) {
390             this.mNotificationAssistantAccessGrantedCallback = callback;
391         }
392 
393         interface NotificationAssistantAccessGrantedCallback {
onGranted(ComponentName assistant, int userId, boolean granted)394             void onGranted(ComponentName assistant, int userId, boolean granted);
395         }
396     }
397 
398     private class TestableToastCallback extends ITransientNotification.Stub {
399         @Override
show(IBinder windowToken)400         public void show(IBinder windowToken) {
401         }
402 
403         @Override
hide()404         public void hide() {
405         }
406     }
407 
408     @Before
setUp()409     public void setUp() throws Exception {
410         // Shell permisssions will override permissions of our app, so add all necessary permissions
411         // for this test here:
412         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
413                 "android.permission.WRITE_DEVICE_CONFIG",
414                 "android.permission.READ_DEVICE_CONFIG",
415                 "android.permission.READ_CONTACTS");
416 
417         MockitoAnnotations.initMocks(this);
418 
419         DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
420         when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
421         ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
422 
423         LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
424         LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
425         LocalServices.removeServiceForTest(WindowManagerInternal.class);
426         LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
427         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
428         LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
429         LocalServices.removeServiceForTest(DeviceIdleInternal.class);
430         LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
431         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
432         LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
433         mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
434 
435 
436         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
437 
438         mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
439                 mSystemClock, mNotificationInstanceIdSequence);
440 
441         // Use this testable looper.
442         mTestableLooper = TestableLooper.get(this);
443         // MockPackageManager - default returns ApplicationInfo with matching calling UID
444         mContext.setMockPackageManager(mPackageManagerClient);
445 
446         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
447                 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
448                     Object[] args = invocation.getArguments();
449                     return getApplicationInfo((String) args[0], mUid);
450                 });
451         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
452                 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
453                     Object[] args = invocation.getArguments();
454                     return getApplicationInfo((String) args[0], mUid);
455                 });
456         when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
457         final LightsManager mockLightsManager = mock(LightsManager.class);
458         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
459         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
460         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
461         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
462         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
463         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
464         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
465 
466         // write to a test file; the system file isn't readable from tests
467         mFile = new File(mContext.getCacheDir(), "test.xml");
468         mFile.createNewFile();
469         final String preupgradeXml = "<notification-policy></notification-policy>";
470         mPolicyFile = new AtomicFile(mFile);
471         FileOutputStream fos = mPolicyFile.startWrite();
472         fos.write(preupgradeXml.getBytes());
473         mPolicyFile.finishWrite(fos);
474 
475         // Setup managed services
476         mListener = mListeners.new ManagedServiceInfo(
477                 null, new ComponentName(PKG, "test_class"),
478                 UserHandle.getUserId(mUid), true, null, 0);
479         ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
480         ArraySet<ComponentName> components = new ArraySet<>();
481         components.add(defaultComponent);
482         when(mListeners.getDefaultComponents()).thenReturn(components);
483         when(mConditionProviders.getDefaultPackages())
484                 .thenReturn(new ArraySet<>(Arrays.asList("config")));
485         when(mAssistants.getDefaultComponents()).thenReturn(components);
486         when(mAssistants.queryPackageForServices(
487                 anyString(), anyInt(), anyInt())).thenReturn(components);
488         when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener);
489         ManagedServices.Config listenerConfig = new ManagedServices.Config();
490         listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
491         when(mListeners.getConfig()).thenReturn(listenerConfig);
492         ManagedServices.Config assistantConfig = new ManagedServices.Config();
493         assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
494         when(mAssistants.getConfig()).thenReturn(assistantConfig);
495         ManagedServices.Config dndConfig = new ManagedServices.Config();
496         dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
497         when(mConditionProviders.getConfig()).thenReturn(dndConfig);
498 
499         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
500 
501         mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
502                 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
503                 mListeners, mAssistants, mConditionProviders,
504                 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
505                 mGroupHelper, mAm, mAtm, mAppUsageStats,
506                 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
507                 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
508                 mock(TelephonyManager.class),
509                 mock(ActivityManagerInternal.class));
510         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
511 
512         mService.setAudioManager(mAudioManager);
513 
514         mShortcutHelper = mService.getShortcutHelper();
515         mShortcutHelper.setLauncherApps(mLauncherApps);
516         mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
517 
518         // Pretend the shortcut exists
519         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
520         ShortcutInfo info = mock(ShortcutInfo.class);
521         when(info.getPackage()).thenReturn(PKG);
522         when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID);
523         when(info.getUserId()).thenReturn(USER_SYSTEM);
524         when(info.isLongLived()).thenReturn(true);
525         when(info.isEnabled()).thenReturn(true);
526         shortcutInfos.add(info);
527         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
528         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
529                 anyString(), anyInt(), any())).thenReturn(true);
530 
531         // Set the testable bubble extractor
532         RankingHelper rankingHelper = mService.getRankingHelper();
533         BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
534         extractor.setActivityManager(mActivityManager);
535 
536         // Tests call directly into the Binder.
537         mBinderService = mService.getBinderService();
538         mInternalService = mService.getInternalService();
539 
540         mBinderService.createNotificationChannels(
541                 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
542         mBinderService.createNotificationChannels(
543                 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
544         mBinderService.createNotificationChannels(
545                 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
546         assertNotNull(mBinderService.getNotificationChannel(
547                 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
548         clearInvocations(mRankingHandler);
549     }
550 
551     @After
assertNotificationRecordLoggerCallsValid()552     public void assertNotificationRecordLoggerCallsValid() {
553         for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
554             if (call.wasLogged) {
555                 assertNotNull(call.event);
556             }
557         }
558     }
559 
560     @After
tearDown()561     public void tearDown() throws Exception {
562         if (mFile != null) mFile.delete();
563         clearDeviceConfig();
564         mService.unregisterDeviceConfigChange();
565         InstrumentationRegistry.getInstrumentation()
566                 .getUiAutomation().dropShellPermissionIdentity();
567     }
568 
generateResetComponentValues()569     private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
570         ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
571         changed.put(true, new ArrayList<>());
572         changed.put(false, new ArrayList<>());
573         return changed;
574     }
getApplicationInfo(String pkg, int uid)575     private ApplicationInfo getApplicationInfo(String pkg, int uid) {
576         final ApplicationInfo applicationInfo = new ApplicationInfo();
577         applicationInfo.uid = uid;
578         switch (pkg) {
579             case PKG_N_MR1:
580                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
581                 break;
582             case PKG_O:
583                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
584                 break;
585             case PKG_P:
586                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
587                 break;
588             default:
589                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
590                 break;
591         }
592         return applicationInfo;
593     }
594 
waitForIdle()595     public void waitForIdle() {
596         mTestableLooper.processAllMessages();
597     }
598 
setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, int pkgPref, boolean channelEnabled)599     private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
600             int pkgPref, boolean channelEnabled) {
601         Settings.Global.putInt(mContext.getContentResolver(),
602                 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
603         mService.mPreferencesHelper.updateBubblesEnabled();
604         assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled());
605         try {
606             mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
607         } catch (RemoteException e) {
608             e.printStackTrace();
609         }
610         mTestNotificationChannel.setAllowBubbles(channelEnabled);
611     }
612 
generateSbn(String pkg, int uid, long postTime, int userId)613     private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
614         Notification.Builder nb = new Notification.Builder(mContext, "a")
615                 .setContentTitle("foo")
616                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
617         StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
618                 "tag" + System.currentTimeMillis(), uid, 0,
619                 nb.build(), new UserHandle(userId), null, postTime);
620         return sbn;
621     }
622 
generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)623     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
624             String groupKey, boolean isSummary) {
625         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
626                 .setContentTitle("foo")
627                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
628                 .setGroup(groupKey)
629                 .setGroupSummary(isSummary);
630         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
631                 "tag" + System.currentTimeMillis(), mUid, 0,
632                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
633         return new NotificationRecord(mContext, sbn, channel);
634     }
635 
generateNotificationRecord(NotificationChannel channel)636     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
637         return generateNotificationRecord(channel, null);
638     }
639 
generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)640     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
641             Notification.TvExtender extender) {
642         if (channel == null) {
643             channel = mTestNotificationChannel;
644         }
645         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
646                 .setContentTitle("foo")
647                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
648         if (extender != null) {
649             nb.extend(extender);
650         }
651         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
652                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
653         return new NotificationRecord(mContext, sbn, channel);
654     }
655 
generateNotificationRecord(NotificationChannel channel, int userId)656     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
657         if (channel == null) {
658             channel = mTestNotificationChannel;
659         }
660         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
661                 .setContentTitle("foo")
662                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
663         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
664                 nb.build(), new UserHandle(userId), null, 0);
665         return new NotificationRecord(mContext, sbn, channel);
666     }
667 
generateMessageBubbleNotifRecord(NotificationChannel channel, String tag)668     private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
669             String tag) {
670         return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
671     }
672 
generateMessageBubbleNotifRecord(boolean addMetadata, NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)673     private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
674             NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
675         if (channel == null) {
676             channel = mTestNotificationChannel;
677         }
678         if (tag == null) {
679             tag = "tag";
680         }
681         Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
682         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
683                 tag, mUid, 0,
684                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
685         return new NotificationRecord(mContext, sbn, channel);
686     }
687 
getSignalExtractorSideEffects()688     private Map<String, Answer> getSignalExtractorSideEffects() {
689         Map<String, Answer> answers = new ArrayMap<>();
690 
691         answers.put("override group key", invocationOnMock -> {
692             ((NotificationRecord) invocationOnMock.getArguments()[0])
693                     .setOverrideGroupKey("bananas");
694             return null;
695         });
696         answers.put("override people", invocationOnMock -> {
697             ((NotificationRecord) invocationOnMock.getArguments()[0])
698                     .setPeopleOverride(new ArrayList<>());
699             return null;
700         });
701         answers.put("snooze criteria", invocationOnMock -> {
702             ((NotificationRecord) invocationOnMock.getArguments()[0])
703                     .setSnoozeCriteria(new ArrayList<>());
704             return null;
705         });
706         answers.put("notification channel", invocationOnMock -> {
707             ((NotificationRecord) invocationOnMock.getArguments()[0])
708                     .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
709             return null;
710         });
711         answers.put("badging", invocationOnMock -> {
712             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
713             r.setShowBadge(!r.canShowBadge());
714             return null;
715         });
716         answers.put("bubbles", invocationOnMock -> {
717             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
718             r.setAllowBubble(!r.canBubble());
719             return null;
720         });
721         answers.put("package visibility", invocationOnMock -> {
722             ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
723                     Notification.VISIBILITY_SECRET);
724             return null;
725         });
726 
727         return answers;
728     }
729 
clearDeviceConfig()730     private void clearDeviceConfig() {
731         DeviceConfig.resetToDefaults(
732                 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
733     }
734 
setDefaultAssistantInDeviceConfig(String componentName)735     private void setDefaultAssistantInDeviceConfig(String componentName) {
736         DeviceConfig.setProperty(
737                 DeviceConfig.NAMESPACE_SYSTEMUI,
738                 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
739                 componentName,
740                 false);
741     }
742 
getMessageStyleNotifBuilder(boolean addBubbleMetadata, String groupKey, boolean isSummary)743     private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
744             String groupKey, boolean isSummary) {
745         // Give it a person
746         Person person = new Person.Builder()
747                 .setName("bubblebot")
748                 .build();
749         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
750         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
751         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
752         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
753                 inputIntent).addRemoteInput(remoteInput)
754                 .build();
755         // Make it messaging style
756         Notification.Builder nb = new Notification.Builder(mContext,
757                 mTestNotificationChannel.getId())
758                 .setContentTitle("foo")
759                 .setStyle(new Notification.MessagingStyle(person)
760                         .setConversationTitle("Bubble Chat")
761                         .addMessage("Hello?",
762                                 SystemClock.currentThreadTimeMillis() - 300000, person)
763                         .addMessage("Is it me you're looking for?",
764                                 SystemClock.currentThreadTimeMillis(), person)
765                 )
766                 .setActions(replyAction)
767                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
768                 .setShortcutId(VALID_CONVO_SHORTCUT_ID)
769                 .setGroupSummary(isSummary);
770         if (groupKey != null) {
771             nb.setGroup(groupKey);
772         }
773         if (addBubbleMetadata) {
774             nb.setBubbleMetadata(getBubbleMetadata());
775         }
776         return nb;
777     }
778 
getBubbleMetadata()779     private Notification.BubbleMetadata getBubbleMetadata() {
780         PendingIntent pendingIntent = mock(PendingIntent.class);
781         Intent intent = mock(Intent.class);
782         when(pendingIntent.getIntent()).thenReturn(intent);
783 
784         ActivityInfo info = new ActivityInfo();
785         info.resizeMode = RESIZE_MODE_RESIZEABLE;
786         when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
787 
788         return new Notification.BubbleMetadata.Builder(
789                 pendingIntent,
790                 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
791                 .build();
792     }
793 
addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)794     private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
795             throws RemoteException {
796 
797         String groupKey = "BUBBLE_GROUP";
798 
799         // Notification that has bubble metadata
800         NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
801                 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
802 
803         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
804                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
805                 nrBubble.getSbn().getUserId());
806         waitForIdle();
807 
808         // Make sure we are a bubble
809         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
810         assertEquals(1, notifsAfter.length);
811         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
812 
813         // Notification without bubble metadata
814         NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
815                 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
816 
817         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
818                 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
819                 nrPlain.getSbn().getUserId());
820         waitForIdle();
821 
822         notifsAfter = mBinderService.getActiveNotifications(PKG);
823         assertEquals(2, notifsAfter.length);
824 
825         // Summary notification for both of those
826         NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
827                 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
828 
829         if (summaryAutoCancel) {
830             nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
831         }
832         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
833                 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
834                 nrSummary.getSbn().getUserId());
835         waitForIdle();
836 
837         notifsAfter = mBinderService.getActiveNotifications(PKG);
838         assertEquals(3, notifsAfter.length);
839 
840         return nrSummary;
841     }
842 
843     @Test
testLimitTimeOutBroadcast()844     public void testLimitTimeOutBroadcast() {
845         NotificationChannel channel = new NotificationChannel("id", "name",
846                 NotificationManager.IMPORTANCE_HIGH);
847         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
848                 .setContentTitle("foo")
849                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
850                 .setTimeoutAfter(1);
851 
852         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
853                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
854         NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
855 
856         mService.scheduleTimeoutLocked(r);
857         ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
858         verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
859         assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
860                 captor.getValue().getIntent().getPackage());
861     }
862 
863     @Test
testDefaultAssistant_overrideDefault()864     public void testDefaultAssistant_overrideDefault() {
865         final int userId = 0;
866         final String testComponent = "package/class";
867         final List<UserInfo> userInfos = new ArrayList<>();
868         userInfos.add(new UserInfo(0, "", 0));
869         final ArraySet<ComponentName> validAssistants = new ArraySet<>();
870         validAssistants.add(ComponentName.unflattenFromString(testComponent));
871         when(mActivityManager.isLowRamDevice()).thenReturn(false);
872         when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
873                 .thenReturn(validAssistants);
874         when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
875         when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
876 
877         mService.setDefaultAssistantForUser(userId);
878 
879         verify(mAssistants).setPackageOrComponentEnabled(
880                 eq(testComponent), eq(userId), eq(true), eq(true));
881     }
882 
883     @Test
testCreateNotificationChannels_SingleChannel()884     public void testCreateNotificationChannels_SingleChannel() throws Exception {
885         final NotificationChannel channel =
886                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
887         mBinderService.createNotificationChannels(PKG,
888                 new ParceledListSlice(Arrays.asList(channel)));
889         final NotificationChannel createdChannel =
890                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
891         assertTrue(createdChannel != null);
892     }
893 
894     @Test
testCreateNotificationChannels_NullChannelThrowsException()895     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
896         try {
897             mBinderService.createNotificationChannels(PKG,
898                     new ParceledListSlice(Arrays.asList((Object[])null)));
899             fail("Exception should be thrown immediately.");
900         } catch (NullPointerException e) {
901             // pass
902         }
903     }
904 
905     @Test
testCreateNotificationChannels_TwoChannels()906     public void testCreateNotificationChannels_TwoChannels() throws Exception {
907         final NotificationChannel channel1 =
908                 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
909         final NotificationChannel channel2 =
910                 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
911         mBinderService.createNotificationChannels(PKG,
912                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
913         assertTrue(mBinderService.getNotificationChannel(
914                 PKG, mContext.getUserId(), PKG, "id1") != null);
915         assertTrue(mBinderService.getNotificationChannel(
916                 PKG, mContext.getUserId(), PKG, "id2") != null);
917     }
918 
919     @Test
testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()920     public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
921             throws Exception {
922         final NotificationChannel channel =
923                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
924         mBinderService.createNotificationChannels(PKG,
925                 new ParceledListSlice(Arrays.asList(channel)));
926 
927         // Recreating the channel doesn't throw, but ignores importance.
928         final NotificationChannel dupeChannel =
929                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
930         mBinderService.createNotificationChannels(PKG,
931                 new ParceledListSlice(Arrays.asList(dupeChannel)));
932         final NotificationChannel createdChannel =
933                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
934         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
935     }
936 
937     @Test
testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()938     public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
939             throws Exception {
940         final NotificationChannel channel =
941                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
942         mBinderService.createNotificationChannels(PKG,
943                 new ParceledListSlice(Arrays.asList(channel)));
944 
945         // Recreating with a lower importance is allowed to modify the channel.
946         final NotificationChannel dupeChannel =
947                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
948         mBinderService.createNotificationChannels(PKG,
949                 new ParceledListSlice(Arrays.asList(dupeChannel)));
950         final NotificationChannel createdChannel =
951                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
952         assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
953     }
954 
955     @Test
testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()956     public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
957             throws Exception {
958         final NotificationChannel channel =
959                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
960         mBinderService.createNotificationChannels(PKG,
961                 new ParceledListSlice(Arrays.asList(channel)));
962 
963         // The user modifies importance directly, can no longer be changed by the app.
964         final NotificationChannel updatedChannel =
965                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
966         mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
967 
968         // Recreating with a lower importance leaves channel unchanged.
969         final NotificationChannel dupeChannel =
970                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
971         mBinderService.createNotificationChannels(PKG,
972                 new ParceledListSlice(Arrays.asList(dupeChannel)));
973         final NotificationChannel createdChannel =
974                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
975         assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
976     }
977 
978     @Test
testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()979     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
980             throws Exception {
981         final NotificationChannel channel1 =
982                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
983         final NotificationChannel channel2 =
984                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
985         mBinderService.createNotificationChannels(PKG,
986                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
987         final NotificationChannel createdChannel =
988                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
989         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
990     }
991 
992     @Test
testBlockedNotifications_suspended()993     public void testBlockedNotifications_suspended() throws Exception {
994         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
995 
996         NotificationChannel channel = new NotificationChannel("id", "name",
997                 IMPORTANCE_HIGH);
998         NotificationRecord r = generateNotificationRecord(channel);
999 
1000         // isBlocked is only used for user blocking, not app suspension
1001         assertFalse(mService.isBlocked(r, mUsageStats));
1002     }
1003 
1004     @Test
testBlockedNotifications_blockedChannel()1005     public void testBlockedNotifications_blockedChannel() throws Exception {
1006         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1007 
1008         NotificationChannel channel = new NotificationChannel("id", "name",
1009                 NotificationManager.IMPORTANCE_NONE);
1010         NotificationRecord r = generateNotificationRecord(channel);
1011         assertTrue(mService.isBlocked(r, mUsageStats));
1012         verify(mUsageStats, times(1)).registerBlocked(eq(r));
1013 
1014         mBinderService.createNotificationChannels(
1015                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1016         final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1017         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1018                 "testBlockedNotifications_blockedChannel",
1019                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1020         waitForIdle();
1021         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1022     }
1023 
1024     @Test
testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()1025     public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
1026             throws Exception {
1027         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1028 
1029         NotificationChannel channel = new NotificationChannel("blocked", "name",
1030                 NotificationManager.IMPORTANCE_NONE);
1031         mBinderService.createNotificationChannels(
1032                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1033 
1034         final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1035         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1036         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1037                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1038         waitForIdle();
1039         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1040         assertEquals(IMPORTANCE_LOW,
1041                 mService.getNotificationRecord(sbn.getKey()).getImportance());
1042         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1043                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1044     }
1045 
1046     @Test
testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()1047     public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
1048             throws Exception {
1049         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1050 
1051         NotificationChannel channel =
1052                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
1053         mBinderService.createNotificationChannels(
1054                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1055 
1056         NotificationChannel update =
1057                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1058         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1059         waitForIdle();
1060         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1061                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1062 
1063         StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1064         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1065         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1066                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1067         waitForIdle();
1068         // The first time a foreground service notification is shown, we allow the channel
1069         // to be updated to allow it to be seen.
1070         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1071         assertEquals(IMPORTANCE_LOW,
1072                 mService.getNotificationRecord(sbn.getKey()).getImportance());
1073         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1074                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1075         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1076         waitForIdle();
1077 
1078         update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1079         update.setFgServiceShown(true);
1080         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1081         waitForIdle();
1082         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1083                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1084 
1085         sbn = generateNotificationRecord(channel).getSbn();
1086         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1087         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1088                 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
1089                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1090         waitForIdle();
1091         // The second time it is shown, we keep the user's preference.
1092         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1093         assertNull(mService.getNotificationRecord(sbn.getKey()));
1094         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1095                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1096     }
1097 
1098     @Test
testBlockedNotifications_blockedChannelGroup()1099     public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1100         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1101         mService.setPreferencesHelper(mPreferencesHelper);
1102         when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1103                 thenReturn(true);
1104 
1105         NotificationChannel channel = new NotificationChannel("id", "name",
1106                 NotificationManager.IMPORTANCE_HIGH);
1107         channel.setGroup("something");
1108         NotificationRecord r = generateNotificationRecord(channel);
1109         assertTrue(mService.isBlocked(r, mUsageStats));
1110         verify(mUsageStats, times(1)).registerBlocked(eq(r));
1111     }
1112 
1113     @Test
testEnqueuedBlockedNotifications_blockedApp()1114     public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
1115         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1116 
1117         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1118 
1119         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1120         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1121                 "testEnqueuedBlockedNotifications_blockedApp",
1122                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1123         waitForIdle();
1124         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1125     }
1126 
1127     @Test
testEnqueuedBlockedNotifications_blockedAppForegroundService()1128     public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1129         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1130 
1131         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1132 
1133         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1134         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1135         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1136                 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
1137                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1138         waitForIdle();
1139         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1140         assertNull(mService.getNotificationRecord(sbn.getKey()));
1141     }
1142 
1143     /**
1144      * Confirm the system user on automotive devices can use car categories
1145      */
1146     @Test
testEnqueuedRestrictedNotifications_asSystem()1147     public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
1148         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1149                 .thenReturn(true);
1150         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1151                 Notification.CATEGORY_CAR_WARNING,
1152                 Notification.CATEGORY_CAR_INFORMATION);
1153         int id = 0;
1154         for (String category: categories) {
1155             final StatusBarNotification sbn =
1156                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
1157             sbn.getNotification().category = category;
1158             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1159                     "testEnqueuedRestrictedNotifications_asSystem",
1160                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1161         }
1162         waitForIdle();
1163         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1164     }
1165 
1166 
1167     /**
1168      * Confirm restricted notification categories only apply to automotive.
1169      */
1170     @Test
testEnqueuedRestrictedNotifications_notAutomotive()1171     public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1172         mService.isSystemUid = false;
1173         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1174                 .thenReturn(false);
1175         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1176                 Notification.CATEGORY_CAR_WARNING,
1177                 Notification.CATEGORY_CAR_INFORMATION);
1178         int id = 0;
1179         for (String category: categories) {
1180             final StatusBarNotification sbn =
1181                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
1182             sbn.getNotification().category = category;
1183             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1184                     "testEnqueuedRestrictedNotifications_notAutomotive",
1185                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1186         }
1187         waitForIdle();
1188         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1189     }
1190 
1191     /**
1192      * Confirm if a non-system user tries to use the car categories on a automotive device that
1193      * they will get a security exception
1194      */
1195     @Test
testEnqueuedRestrictedNotifications_badUser()1196     public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1197         mService.isSystemUid = false;
1198         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1199                 .thenReturn(true);
1200         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1201                 Notification.CATEGORY_CAR_WARNING,
1202                 Notification.CATEGORY_CAR_INFORMATION);
1203         for (String category: categories) {
1204             final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1205             sbn.getNotification().category = category;
1206             try {
1207                 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1208                         "testEnqueuedRestrictedNotifications_badUser",
1209                         sbn.getId(), sbn.getNotification(), sbn.getUserId());
1210                 fail("Calls from non system apps should not allow use of restricted categories");
1211             } catch (SecurityException e) {
1212                 // pass
1213             }
1214         }
1215         waitForIdle();
1216         assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1217     }
1218 
1219     @Test
testEnqueuedRestrictedNotifications_asSuwApp()1220     public void testEnqueuedRestrictedNotifications_asSuwApp() throws Exception {
1221         LocalServices.removeServiceForTest(PackageManagerInternal.class);
1222         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
1223         when(mPackageManagerInternal.getSetupWizardPackageName()).thenReturn(PKG);
1224 
1225         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1226                 .thenReturn(true);
1227 
1228         final StatusBarNotification sbn =
1229                 generateNotificationRecord(mTestNotificationChannel, 0, "", false).getSbn();
1230         sbn.getNotification().category = Notification.CATEGORY_CAR_INFORMATION;
1231         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1232                 "testEnqueuedRestrictedNotifications_asSuwApp",
1233                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1234 
1235         waitForIdle();
1236         assertEquals(1, mBinderService.getActiveNotifications(PKG).length);
1237     }
1238 
1239     @Test
testBlockedNotifications_blockedByAssistant()1240     public void testBlockedNotifications_blockedByAssistant() throws Exception {
1241         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1242         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
1243 
1244         NotificationChannel channel = new NotificationChannel("id", "name",
1245                 NotificationManager.IMPORTANCE_HIGH);
1246         NotificationRecord r = generateNotificationRecord(channel);
1247         mService.addEnqueuedNotification(r);
1248 
1249         Bundle bundle = new Bundle();
1250         bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
1251         Adjustment adjustment = new Adjustment(
1252                 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
1253         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
1254 
1255         NotificationManagerService.PostNotificationRunnable runnable =
1256                 mService.new PostNotificationRunnable(r.getKey());
1257         runnable.run();
1258         waitForIdle();
1259 
1260         verify(mUsageStats, never()).registerPostedByApp(any());
1261     }
1262 
1263     @Test
testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()1264     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
1265         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1266                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1267                 generateNotificationRecord(null).getNotification(), 0);
1268         waitForIdle();
1269         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
1270         assertEquals(1, notifs.length);
1271         assertEquals(1, mService.getNotificationRecordCount());
1272     }
1273 
1274     @Test
testEnqueueNotificationWithTag_WritesExpectedLogs()1275     public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
1276         final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1277         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1278                 generateNotificationRecord(null).getNotification(), 0);
1279         waitForIdle();
1280         assertEquals(1, mNotificationRecordLogger.numCalls());
1281 
1282         NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
1283         assertTrue(call.wasLogged);
1284         assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1285                 call.event);
1286         assertNotNull(call.r);
1287         assertNull(call.old);
1288         assertEquals(0, call.position);
1289         assertEquals(0, call.buzzBeepBlink);
1290         assertEquals(PKG, call.r.getSbn().getPackageName());
1291         assertEquals(0, call.r.getSbn().getId());
1292         assertEquals(tag, call.r.getSbn().getTag());
1293         assertEquals(1, call.getInstanceId());  // Fake instance IDs are assigned in order
1294     }
1295 
1296     @Test
testEnqueueNotificationWithTag_LogsOnMajorUpdates()1297     public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1298         final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1299         Notification original = new Notification.Builder(mContext,
1300                 mTestNotificationChannel.getId())
1301                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1302         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1303         Notification update = new Notification.Builder(mContext,
1304                 mTestNotificationChannel.getId())
1305                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1306                 .setCategory(Notification.CATEGORY_ALARM).build();
1307         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1308         waitForIdle();
1309         assertEquals(2, mNotificationRecordLogger.numCalls());
1310 
1311         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1312         assertEquals(
1313                 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1314                 mNotificationRecordLogger.event(0));
1315         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
1316 
1317         assertTrue(mNotificationRecordLogger.get(1).wasLogged);
1318         assertEquals(
1319                 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED,
1320                 mNotificationRecordLogger.event(1));
1321         // Instance ID doesn't change on update of an active notification
1322         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
1323     }
1324 
1325     @Test
testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate()1326     public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1327         final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
1328         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1329                 generateNotificationRecord(null).getNotification(), 0);
1330         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1331                 generateNotificationRecord(null).getNotification(), 0);
1332         waitForIdle();
1333         assertEquals(2, mNotificationRecordLogger.numCalls());
1334         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1335         assertEquals(
1336                 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1337                 mNotificationRecordLogger.event(0));
1338         assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1339         assertNull(mNotificationRecordLogger.event(1));
1340     }
1341 
1342     @Test
testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate()1343     public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1344         final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1345         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1346                 generateNotificationRecord(null).getNotification(),
1347                 0);
1348         final Notification notif = generateNotificationRecord(null).getNotification();
1349         notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1350         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1351         waitForIdle();
1352         assertEquals(2, mNotificationRecordLogger.numCalls());
1353         assertEquals(
1354                 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1355                 mNotificationRecordLogger.event(0));
1356         assertNull(mNotificationRecordLogger.event(1));
1357     }
1358 
1359     @Test
testEnqueueNotificationWithTag_LogsAgainAfterCancel()1360     public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1361         final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1362         Notification notification = new Notification.Builder(mContext,
1363                 mTestNotificationChannel.getId())
1364                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1365         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1366         waitForIdle();
1367         mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1368         waitForIdle();
1369         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1370         waitForIdle();
1371         assertEquals(3, mNotificationRecordLogger.numCalls());
1372 
1373         assertEquals(
1374                 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1375                 mNotificationRecordLogger.event(0));
1376         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1377         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
1378 
1379         assertEquals(
1380                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
1381                 mNotificationRecordLogger.event(1));
1382         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
1383 
1384         assertEquals(
1385                 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1386                 mNotificationRecordLogger.event(2));
1387         assertTrue(mNotificationRecordLogger.get(2).wasLogged);
1388         // New instance ID because notification was canceled before re-post
1389         assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
1390     }
1391 
1392     @Test
testCancelNonexistentNotification()1393     public void testCancelNonexistentNotification() throws Exception {
1394         mBinderService.cancelNotificationWithTag(PKG, PKG,
1395                 "testCancelNonexistentNotification", 0, 0);
1396         waitForIdle();
1397         // The notification record logger doesn't even get called when a nonexistent notification
1398         // is cancelled, because that happens very frequently and is not interesting.
1399         assertEquals(0, mNotificationRecordLogger.numCalls());
1400     }
1401 
1402     @Test
testCancelNotificationImmediatelyAfterEnqueue()1403     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
1404         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1405                 "testCancelNotificationImmediatelyAfterEnqueue", 0,
1406                 generateNotificationRecord(null).getNotification(), 0);
1407         mBinderService.cancelNotificationWithTag(PKG, PKG,
1408                 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
1409         waitForIdle();
1410         StatusBarNotification[] notifs =
1411                 mBinderService.getActiveNotifications(PKG);
1412         assertEquals(0, notifs.length);
1413         assertEquals(0, mService.getNotificationRecordCount());
1414     }
1415 
1416     @Test
testPostCancelPostNotifiesListeners()1417     public void testPostCancelPostNotifiesListeners() throws Exception {
1418         // WHEN a notification is posted
1419         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1420         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1421                 sbn.getNotification(), sbn.getUserId());
1422         mSystemClock.advanceTime(1);
1423         // THEN it is canceled
1424         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1425         mSystemClock.advanceTime(1);
1426         // THEN it is posted again (before the cancel has a chance to finish)
1427         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1428                 sbn.getNotification(), sbn.getUserId());
1429         // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
1430         waitForIdle();
1431 
1432         // The final enqueue made it to the listener instead of being canceled
1433         StatusBarNotification[] notifs =
1434                 mBinderService.getActiveNotifications(PKG);
1435         assertEquals(1, notifs.length);
1436         assertEquals(1, mService.getNotificationRecordCount());
1437     }
1438 
1439     @Test
testChangeSystemTimeAfterPost_thenCancel_noFgs()1440     public void testChangeSystemTimeAfterPost_thenCancel_noFgs() throws Exception {
1441         // GIVEN time X
1442         mSystemClock.setCurrentTimeMillis(10000);
1443 
1444         // GIVEN a notification is posted
1445         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1446         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1447                 sbn.getNotification(), sbn.getUserId());
1448         mSystemClock.advanceTime(1);
1449         waitForIdle();
1450 
1451         // THEN the system time is changed to an earlier time
1452         mSystemClock.setCurrentTimeMillis(5000);
1453 
1454         // THEN a cancel is requested
1455         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1456         waitForIdle();
1457 
1458         // It should work
1459         StatusBarNotification[] notifs =
1460                 mBinderService.getActiveNotifications(PKG);
1461         assertEquals(0, notifs.length);
1462         assertEquals(0, mService.getNotificationRecordCount());
1463     }
1464 
1465     @Test
testChangeSystemTimeAfterPost_thenCancel_fgs()1466     public void testChangeSystemTimeAfterPost_thenCancel_fgs() throws Exception {
1467         // GIVEN time X
1468         mSystemClock.setCurrentTimeMillis(10000);
1469 
1470         // GIVEN a notification is posted
1471         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1472         sbn.getNotification().flags =
1473                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1474         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1475                 sbn.getNotification(), sbn.getUserId());
1476         mSystemClock.advanceTime(1);
1477         waitForIdle();
1478 
1479         // THEN the system time is changed to an earlier time
1480         mSystemClock.setCurrentTimeMillis(5000);
1481 
1482         // THEN a cancel is requested
1483         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1484         waitForIdle();
1485 
1486         // It should work
1487         StatusBarNotification[] notifs =
1488                 mBinderService.getActiveNotifications(PKG);
1489         assertEquals(0, notifs.length);
1490         assertEquals(0, mService.getNotificationRecordCount());
1491     }
1492 
1493     @Test
testCancelNotificationWhilePostedAndEnqueued()1494     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
1495         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1496                 "testCancelNotificationWhilePostedAndEnqueued", 0,
1497                 generateNotificationRecord(null).getNotification(), 0);
1498         waitForIdle();
1499         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1500                 "testCancelNotificationWhilePostedAndEnqueued", 0,
1501                 generateNotificationRecord(null).getNotification(), 0);
1502         mBinderService.cancelNotificationWithTag(PKG, PKG,
1503                 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
1504         waitForIdle();
1505         StatusBarNotification[] notifs =
1506                 mBinderService.getActiveNotifications(PKG);
1507         assertEquals(0, notifs.length);
1508         assertEquals(0, mService.getNotificationRecordCount());
1509         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1510         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1511         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
1512     }
1513 
1514     @Test
testDelayCancelWhenEnqueuedHasNotPosted()1515     public void testDelayCancelWhenEnqueuedHasNotPosted() throws Exception {
1516         // Don't allow PostNotificationRunnables to execute so we can set up problematic state
1517         mService.trapEnqueuedNotifications = true;
1518         // GIVEN an enqueued notification
1519         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1520                 "testDelayCancelWhenEnqueuedHasNotPosted", 0,
1521                 generateNotificationRecord(null).getNotification(), 0);
1522         mSystemClock.advanceTime(1);
1523         // WHEN a cancel is requested before it has posted
1524         mBinderService.cancelNotificationWithTag(PKG, PKG,
1525                 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0);
1526 
1527         waitForIdle();
1528 
1529         // THEN the cancel notification runnable is captured and associated with that record
1530         ArrayMap<NotificationRecord,
1531                 ArrayList<NotificationManagerService.CancelNotificationRunnable>> delayed =
1532                         mService.mDelayedCancelations;
1533         Set<NotificationRecord> keySet = delayed.keySet();
1534         assertEquals(1, keySet.size());
1535     }
1536 
1537     @Test
testDelayedCancelsExecuteAfterPost()1538     public void testDelayedCancelsExecuteAfterPost() throws Exception {
1539         // Don't allow PostNotificationRunnables to execute so we can set up problematic state
1540         mService.trapEnqueuedNotifications = true;
1541         // GIVEN an enqueued notification
1542         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1543                 "testDelayCancelWhenEnqueuedHasNotPosted", 0,
1544                 generateNotificationRecord(null).getNotification(), 0);
1545         mSystemClock.advanceTime(1);
1546         // WHEN a cancel is requested before it has posted
1547         mBinderService.cancelNotificationWithTag(PKG, PKG,
1548                 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0);
1549 
1550         waitForIdle();
1551 
1552         // We're now in a state with an a notification awaiting PostNotificationRunnable to execute
1553         // WHEN the PostNotificationRunnable is allowed to execute
1554         mService.drainTrappedRunnableQueue();
1555         waitForIdle();
1556 
1557         // THEN the cancel executes and the notification is removed
1558         StatusBarNotification[] notifs =
1559                 mBinderService.getActiveNotifications(PKG);
1560         assertEquals(0, notifs.length);
1561         assertEquals(0, mService.getNotificationRecordCount());
1562     }
1563 
1564     @Test
testCancelNotificationsFromListenerImmediatelyAfterEnqueue()1565     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
1566         NotificationRecord r = generateNotificationRecord(null);
1567         final StatusBarNotification sbn = r.getSbn();
1568         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1569                 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
1570                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1571         mBinderService.cancelNotificationsFromListener(null, null);
1572         waitForIdle();
1573         StatusBarNotification[] notifs =
1574                 mBinderService.getActiveNotifications(sbn.getPackageName());
1575         assertEquals(0, notifs.length);
1576         assertEquals(0, mService.getNotificationRecordCount());
1577     }
1578 
1579     @Test
testCancelAllNotificationsImmediatelyAfterEnqueue()1580     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
1581         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1582         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1583                 "testCancelAllNotificationsImmediatelyAfterEnqueue",
1584                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1585         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1586         waitForIdle();
1587         StatusBarNotification[] notifs =
1588                 mBinderService.getActiveNotifications(sbn.getPackageName());
1589         assertEquals(0, notifs.length);
1590         assertEquals(0, mService.getNotificationRecordCount());
1591     }
1592 
1593     @Test
testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()1594     public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1595             throws Exception {
1596         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1597         sbn.getNotification().flags =
1598                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1599         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1600                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1601         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1602         waitForIdle();
1603         verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1604         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1605     }
1606 
1607     @Test
testUserInitiatedClearAll_noLeak()1608     public void testUserInitiatedClearAll_noLeak() throws Exception {
1609         final NotificationRecord n = generateNotificationRecord(
1610                 mTestNotificationChannel, 1, "group", true);
1611 
1612         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1613                 "testUserInitiatedClearAll_noLeak",
1614                 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
1615         waitForIdle();
1616 
1617         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1618                 n.getUserId());
1619         waitForIdle();
1620         StatusBarNotification[] notifs =
1621                 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
1622         assertEquals(0, notifs.length);
1623         assertEquals(0, mService.getNotificationRecordCount());
1624         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1625         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1626         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
1627     }
1628 
1629     @Test
testCancelAllNotificationsCancelsChildren()1630     public void testCancelAllNotificationsCancelsChildren() throws Exception {
1631         final NotificationRecord parent = generateNotificationRecord(
1632                 mTestNotificationChannel, 1, "group1", true);
1633         final NotificationRecord child = generateNotificationRecord(
1634                 mTestNotificationChannel, 2, "group1", false);
1635 
1636         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1637                 "testCancelAllNotificationsCancelsChildren",
1638                 parent.getSbn().getId(), parent.getSbn().getNotification(),
1639                 parent.getSbn().getUserId());
1640         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1641                 "testCancelAllNotificationsCancelsChildren",
1642                 child.getSbn().getId(), child.getSbn().getNotification(),
1643                 child.getSbn().getUserId());
1644         waitForIdle();
1645 
1646         mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
1647         waitForIdle();
1648         assertEquals(0, mService.getNotificationRecordCount());
1649     }
1650 
1651     @Test
testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()1652     public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1653         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1654         for (int i = 0; i < 10; i++) {
1655             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1656                     "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
1657                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1658         }
1659         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1660         waitForIdle();
1661 
1662         assertEquals(0, mService.getNotificationRecordCount());
1663     }
1664 
1665     @Test
testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()1666     public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1667         final NotificationRecord parent = generateNotificationRecord(
1668                 mTestNotificationChannel, 1, "group1", true);
1669         final NotificationRecord parentAsChild = generateNotificationRecord(
1670                 mTestNotificationChannel, 1, "group1", false);
1671         final NotificationRecord child = generateNotificationRecord(
1672                 mTestNotificationChannel, 2, "group1", false);
1673 
1674         // fully post parent notification
1675         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1676                 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
1677                 parent.getSbn().getId(), parent.getSbn().getNotification(),
1678                 parent.getSbn().getUserId());
1679         waitForIdle();
1680 
1681         // enqueue the child several times
1682         for (int i = 0; i < 10; i++) {
1683             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1684                     "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
1685                     child.getSbn().getId(), child.getSbn().getNotification(),
1686                     child.getSbn().getUserId());
1687         }
1688         // make the parent a child, which will cancel the child notification
1689         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1690                 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
1691                 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
1692                 parentAsChild.getSbn().getUserId());
1693         waitForIdle();
1694 
1695         assertEquals(0, mService.getNotificationRecordCount());
1696     }
1697 
1698     @Test
testAutobundledSummary_notificationAdded()1699     public void testAutobundledSummary_notificationAdded() {
1700         NotificationRecord summary =
1701                 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1702         summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1703         mService.addNotification(summary);
1704         mService.mSummaryByGroupKey.put("pkg", summary);
1705         mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1706         mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1707         mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
1708 
1709         assertTrue(summary.getSbn().isOngoing());
1710     }
1711 
1712     @Test
testAutobundledSummary_notificationRemoved()1713     public void testAutobundledSummary_notificationRemoved() {
1714         NotificationRecord summary =
1715                 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1716         summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1717         summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1718         mService.addNotification(summary);
1719         mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1720         mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1721         mService.mSummaryByGroupKey.put("pkg", summary);
1722 
1723         mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
1724 
1725         assertFalse(summary.getSbn().isOngoing());
1726     }
1727 
1728     @Test
testCancelAllNotifications_IgnoreForegroundService()1729     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1730         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1731         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1732         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1733                 "testCancelAllNotifications_IgnoreForegroundService",
1734                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1735         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1736         waitForIdle();
1737         StatusBarNotification[] notifs =
1738                 mBinderService.getActiveNotifications(sbn.getPackageName());
1739         assertEquals(1, notifs.length);
1740         assertEquals(1, mService.getNotificationRecordCount());
1741     }
1742 
1743     @Test
testCancelAllNotifications_IgnoreOtherPackages()1744     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1745         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1746         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1747         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1748                 "testCancelAllNotifications_IgnoreOtherPackages",
1749                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1750         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1751         waitForIdle();
1752         StatusBarNotification[] notifs =
1753                 mBinderService.getActiveNotifications(sbn.getPackageName());
1754         assertEquals(1, notifs.length);
1755         assertEquals(1, mService.getNotificationRecordCount());
1756     }
1757 
1758     @Test
testCancelAllNotifications_NullPkgRemovesAll()1759     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1760         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1761         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1762                 "testCancelAllNotifications_NullPkgRemovesAll",
1763                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1764         mBinderService.cancelAllNotifications(null, sbn.getUserId());
1765         waitForIdle();
1766         StatusBarNotification[] notifs =
1767                 mBinderService.getActiveNotifications(sbn.getPackageName());
1768         assertEquals(0, notifs.length);
1769         assertEquals(0, mService.getNotificationRecordCount());
1770     }
1771 
1772     @Test
testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()1773     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1774         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1775         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1776                 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
1777                 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
1778         // Null pkg is how we signal a user switch.
1779         mBinderService.cancelAllNotifications(null, sbn.getUserId());
1780         waitForIdle();
1781         StatusBarNotification[] notifs =
1782                 mBinderService.getActiveNotifications(sbn.getPackageName());
1783         assertEquals(1, notifs.length);
1784         assertEquals(1, mService.getNotificationRecordCount());
1785     }
1786 
1787     @Test
testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()1788     public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1789         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1790         sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1791         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1792                 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
1793                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1794         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1795         waitForIdle();
1796         StatusBarNotification[] notifs =
1797                 mBinderService.getActiveNotifications(sbn.getPackageName());
1798         assertEquals(0, notifs.length);
1799     }
1800 
1801     @Test
testCancelAllNotifications_CancelsNoClearFlag()1802     public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1803         final NotificationRecord notif = generateNotificationRecord(
1804                 mTestNotificationChannel, 1, "group", true);
1805         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1806         mService.addNotification(notif);
1807         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1808                 notif.getUserId(), 0, null);
1809         waitForIdle();
1810         StatusBarNotification[] notifs =
1811                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
1812         assertEquals(0, notifs.length);
1813     }
1814 
1815     @Test
testUserInitiatedCancelAllOnClearAll_NoClearFlag()1816     public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1817         final NotificationRecord notif = generateNotificationRecord(
1818                 mTestNotificationChannel, 1, "group", true);
1819         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1820         mService.addNotification(notif);
1821 
1822         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1823                 notif.getUserId());
1824         waitForIdle();
1825         StatusBarNotification[] notifs =
1826                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
1827         assertEquals(1, notifs.length);
1828     }
1829 
1830     @Test
testCancelAllCancelNotificationsFromListener_NoClearFlag()1831     public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1832         final NotificationRecord parent = generateNotificationRecord(
1833                 mTestNotificationChannel, 1, "group", true);
1834         final NotificationRecord child = generateNotificationRecord(
1835                 mTestNotificationChannel, 2, "group", false);
1836         final NotificationRecord child2 = generateNotificationRecord(
1837                 mTestNotificationChannel, 3, "group", false);
1838         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1839         final NotificationRecord newGroup = generateNotificationRecord(
1840                 mTestNotificationChannel, 4, "group2", false);
1841         mService.addNotification(parent);
1842         mService.addNotification(child);
1843         mService.addNotification(child2);
1844         mService.addNotification(newGroup);
1845         mService.getBinderService().cancelNotificationsFromListener(null, null);
1846         waitForIdle();
1847         StatusBarNotification[] notifs =
1848                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
1849         assertEquals(1, notifs.length);
1850     }
1851 
1852     @Test
testUserInitiatedCancelAllWithGroup_NoClearFlag()1853     public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1854         final NotificationRecord parent = generateNotificationRecord(
1855                 mTestNotificationChannel, 1, "group", true);
1856         final NotificationRecord child = generateNotificationRecord(
1857                 mTestNotificationChannel, 2, "group", false);
1858         final NotificationRecord child2 = generateNotificationRecord(
1859                 mTestNotificationChannel, 3, "group", false);
1860         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1861         final NotificationRecord newGroup = generateNotificationRecord(
1862                 mTestNotificationChannel, 4, "group2", false);
1863         mService.addNotification(parent);
1864         mService.addNotification(child);
1865         mService.addNotification(child2);
1866         mService.addNotification(newGroup);
1867         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1868                 parent.getUserId());
1869         waitForIdle();
1870         StatusBarNotification[] notifs =
1871                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
1872         assertEquals(1, notifs.length);
1873     }
1874 
1875     @Test
testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()1876     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
1877         Notification n =
1878                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1879                         .setSmallIcon(android.R.drawable.sym_def_app_icon)
1880                         .build();
1881         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
1882                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
1883         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1884         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
1885                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1886         mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1887                 sbn.getUserId());
1888         waitForIdle();
1889         StatusBarNotification[] notifs =
1890                 mBinderService.getActiveNotifications(sbn.getPackageName());
1891         assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
1892     }
1893 
1894     @Test
testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()1895     public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1896         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1897         sbn.getNotification().flags =
1898                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1899         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1900                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1901         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
1902         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1903                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1904         mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1905                 sbn.getUserId());
1906         waitForIdle();
1907         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1908         assertEquals(0, mService.getNotificationRecordCount());
1909     }
1910 
1911     @Test
testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()1912     public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1913             throws Exception {
1914         final NotificationRecord parent = generateNotificationRecord(
1915                 mTestNotificationChannel, 1, "group", true);
1916         final NotificationRecord child = generateNotificationRecord(
1917                 mTestNotificationChannel, 2, "group", false);
1918         final NotificationRecord child2 = generateNotificationRecord(
1919                 mTestNotificationChannel, 3, "group", false);
1920         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1921         final NotificationRecord newGroup = generateNotificationRecord(
1922                 mTestNotificationChannel, 4, "group2", false);
1923         mService.addNotification(parent);
1924         mService.addNotification(child);
1925         mService.addNotification(child2);
1926         mService.addNotification(newGroup);
1927         mService.getBinderService().cancelNotificationsFromListener(null, null);
1928         waitForIdle();
1929         StatusBarNotification[] notifs =
1930                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
1931         assertEquals(0, notifs.length);
1932     }
1933 
1934     @Test
testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()1935     public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1936             throws Exception {
1937         final NotificationRecord parent = generateNotificationRecord(
1938                 mTestNotificationChannel, 1, "group", true);
1939         final NotificationRecord child = generateNotificationRecord(
1940                 mTestNotificationChannel, 2, "group", false);
1941         final NotificationRecord child2 = generateNotificationRecord(
1942                 mTestNotificationChannel, 3, "group", false);
1943         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1944         final NotificationRecord newGroup = generateNotificationRecord(
1945                 mTestNotificationChannel, 4, "group2", false);
1946         mService.addNotification(parent);
1947         mService.addNotification(child);
1948         mService.addNotification(child2);
1949         mService.addNotification(newGroup);
1950         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1951                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
1952         mService.getBinderService().cancelNotificationsFromListener(null, keys);
1953         waitForIdle();
1954         StatusBarNotification[] notifs =
1955                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
1956         assertEquals(1, notifs.length);
1957     }
1958 
1959     @Test
testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()1960     public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1961         final NotificationRecord parent = generateNotificationRecord(
1962                 mTestNotificationChannel, 1, "group", true);
1963         final NotificationRecord child = generateNotificationRecord(
1964                 mTestNotificationChannel, 2, "group", false);
1965         final NotificationRecord child2 = generateNotificationRecord(
1966                 mTestNotificationChannel, 3, "group", false);
1967         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1968         final NotificationRecord newGroup = generateNotificationRecord(
1969                 mTestNotificationChannel, 4, "group2", false);
1970         mService.addNotification(parent);
1971         mService.addNotification(child);
1972         mService.addNotification(child2);
1973         mService.addNotification(newGroup);
1974         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1975                 parent.getUserId());
1976         waitForIdle();
1977         StatusBarNotification[] notifs =
1978                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
1979         assertEquals(0, notifs.length);
1980     }
1981 
1982     @Test
testGroupInstanceIds()1983     public void testGroupInstanceIds() throws Exception {
1984         final NotificationRecord group1 = generateNotificationRecord(
1985                 mTestNotificationChannel, 1, "group1", true);
1986         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1987                 group1.getSbn().getId(), group1.getSbn().getNotification(),
1988                 group1.getSbn().getUserId());
1989         waitForIdle();
1990 
1991         // same group, child, should be returned
1992         final NotificationRecord group1Child = generateNotificationRecord(
1993                 mTestNotificationChannel, 2, "group1", false);
1994         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1995                 group1Child.getSbn().getId(),
1996                 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
1997         waitForIdle();
1998 
1999         assertEquals(2, mNotificationRecordLogger.numCalls());
2000         assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
2001                 mNotificationRecordLogger.get(1).groupInstanceId.getId());
2002     }
2003 
2004     @Test
testFindGroupNotificationsLocked()2005     public void testFindGroupNotificationsLocked() throws Exception {
2006         // make sure the same notification can be found in both lists and returned
2007         final NotificationRecord group1 = generateNotificationRecord(
2008                 mTestNotificationChannel, 1, "group1", true);
2009         mService.addEnqueuedNotification(group1);
2010         mService.addNotification(group1);
2011 
2012         // should not be returned
2013         final NotificationRecord group2 = generateNotificationRecord(
2014                 mTestNotificationChannel, 2, "group2", true);
2015         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
2016                 group2.getSbn().getId(), group2.getSbn().getNotification(),
2017                 group2.getSbn().getUserId());
2018         waitForIdle();
2019 
2020         // should not be returned
2021         final NotificationRecord nonGroup = generateNotificationRecord(
2022                 mTestNotificationChannel, 3, null, false);
2023         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
2024                 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
2025                 nonGroup.getSbn().getUserId());
2026         waitForIdle();
2027 
2028         // same group, child, should be returned
2029         final NotificationRecord group1Child = generateNotificationRecord(
2030                 mTestNotificationChannel, 4, "group1", false);
2031         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
2032                 group1Child.getSbn().getId(),
2033                 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
2034         waitForIdle();
2035 
2036         List<NotificationRecord> inGroup1 =
2037                 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
2038                         group1.getSbn().getUserId());
2039         assertEquals(3, inGroup1.size());
2040         for (NotificationRecord record : inGroup1) {
2041             assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
2042             assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
2043         }
2044     }
2045 
2046     @Test
testCancelAllNotifications_CancelsNoClearFlagOnGoing()2047     public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
2048         final NotificationRecord notif = generateNotificationRecord(
2049                 mTestNotificationChannel, 1, "group", true);
2050         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2051         mService.addNotification(notif);
2052         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
2053                 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
2054         waitForIdle();
2055         StatusBarNotification[] notifs =
2056                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2057         assertEquals(0, notifs.length);
2058     }
2059 
2060     @Test
testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()2061     public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
2062             throws Exception {
2063         final NotificationRecord parent = generateNotificationRecord(
2064                 mTestNotificationChannel, 1, "group", true);
2065         final NotificationRecord child = generateNotificationRecord(
2066                 mTestNotificationChannel, 2, "group", false);
2067         final NotificationRecord child2 = generateNotificationRecord(
2068                 mTestNotificationChannel, 3, "group", false);
2069         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2070         final NotificationRecord newGroup = generateNotificationRecord(
2071                 mTestNotificationChannel, 4, "group2", false);
2072         mService.addNotification(parent);
2073         mService.addNotification(child);
2074         mService.addNotification(child2);
2075         mService.addNotification(newGroup);
2076         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2077                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2078         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2079         waitForIdle();
2080         StatusBarNotification[] notifs =
2081                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2082         assertEquals(0, notifs.length);
2083     }
2084 
2085     @Test
testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag()2086     public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
2087         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2088         sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2089         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2090                 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
2091                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2092         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2093         waitForIdle();
2094         StatusBarNotification[] notifs =
2095                 mBinderService.getActiveNotifications(sbn.getPackageName());
2096         assertEquals(0, notifs.length);
2097     }
2098 
2099     @Test
testCancelAllNotifications_CancelsOnGoingFlag()2100     public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
2101         final NotificationRecord notif = generateNotificationRecord(
2102                 mTestNotificationChannel, 1, "group", true);
2103         notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2104         mService.addNotification(notif);
2105         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
2106                 notif.getUserId(), 0, null);
2107         waitForIdle();
2108         StatusBarNotification[] notifs =
2109                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2110         assertEquals(0, notifs.length);
2111     }
2112 
2113     @Test
testUserInitiatedCancelAllOnClearAll_OnGoingFlag()2114     public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
2115         final NotificationRecord notif = generateNotificationRecord(
2116                 mTestNotificationChannel, 1, "group", true);
2117         notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2118         mService.addNotification(notif);
2119 
2120         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2121                 notif.getUserId());
2122         waitForIdle();
2123         StatusBarNotification[] notifs =
2124                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2125         assertEquals(1, notifs.length);
2126     }
2127 
2128     @Test
testCancelAllCancelNotificationsFromListener_OnGoingFlag()2129     public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
2130         final NotificationRecord parent = generateNotificationRecord(
2131                 mTestNotificationChannel, 1, "group", true);
2132         final NotificationRecord child = generateNotificationRecord(
2133                 mTestNotificationChannel, 2, "group", false);
2134         final NotificationRecord child2 = generateNotificationRecord(
2135                 mTestNotificationChannel, 3, "group", false);
2136         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2137         final NotificationRecord newGroup = generateNotificationRecord(
2138                 mTestNotificationChannel, 4, "group2", false);
2139         mService.addNotification(parent);
2140         mService.addNotification(child);
2141         mService.addNotification(child2);
2142         mService.addNotification(newGroup);
2143         mService.getBinderService().cancelNotificationsFromListener(null, null);
2144         waitForIdle();
2145         StatusBarNotification[] notifs =
2146                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2147         assertEquals(1, notifs.length);
2148     }
2149 
2150     @Test
testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()2151     public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
2152             throws Exception {
2153         final NotificationRecord parent = generateNotificationRecord(
2154                 mTestNotificationChannel, 1, "group", true);
2155         final NotificationRecord child = generateNotificationRecord(
2156                 mTestNotificationChannel, 2, "group", false);
2157         final NotificationRecord child2 = generateNotificationRecord(
2158                 mTestNotificationChannel, 3, "group", false);
2159         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2160         final NotificationRecord newGroup = generateNotificationRecord(
2161                 mTestNotificationChannel, 4, "group2", false);
2162         mService.addNotification(parent);
2163         mService.addNotification(child);
2164         mService.addNotification(child2);
2165         mService.addNotification(newGroup);
2166         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2167                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2168         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2169         waitForIdle();
2170         StatusBarNotification[] notifs =
2171                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2172         assertEquals(0, notifs.length);
2173     }
2174 
2175     @Test
testUserInitiatedCancelAllWithGroup_OnGoingFlag()2176     public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
2177         final NotificationRecord parent = generateNotificationRecord(
2178                 mTestNotificationChannel, 1, "group", true);
2179         final NotificationRecord child = generateNotificationRecord(
2180                 mTestNotificationChannel, 2, "group", false);
2181         final NotificationRecord child2 = generateNotificationRecord(
2182                 mTestNotificationChannel, 3, "group", false);
2183         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2184         final NotificationRecord newGroup = generateNotificationRecord(
2185                 mTestNotificationChannel, 4, "group2", false);
2186         mService.addNotification(parent);
2187         mService.addNotification(child);
2188         mService.addNotification(child2);
2189         mService.addNotification(newGroup);
2190         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2191                 parent.getUserId());
2192         waitForIdle();
2193         StatusBarNotification[] notifs =
2194                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2195         assertEquals(1, notifs.length);
2196     }
2197 
2198     @Test
testTvExtenderChannelOverride_onTv()2199     public void testTvExtenderChannelOverride_onTv() throws Exception {
2200         mService.setIsTelevision(true);
2201         mService.setPreferencesHelper(mPreferencesHelper);
2202         when(mPreferencesHelper.getNotificationChannel(
2203                 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
2204                         new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
2205 
2206         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
2207         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
2208                 generateNotificationRecord(null, tv).getNotification(), 0);
2209         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
2210                 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
2211     }
2212 
2213     @Test
testTvExtenderChannelOverride_notOnTv()2214     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
2215         mService.setIsTelevision(false);
2216         mService.setPreferencesHelper(mPreferencesHelper);
2217         when(mPreferencesHelper.getNotificationChannel(
2218                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
2219                 mTestNotificationChannel);
2220 
2221         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
2222         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
2223                 0, generateNotificationRecord(null, tv).getNotification(), 0);
2224         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
2225                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
2226                 anyBoolean(), anyBoolean());
2227     }
2228 
2229     @Test
testUpdateAppNotifyCreatorBlock()2230     public void testUpdateAppNotifyCreatorBlock() throws Exception {
2231         mService.setPreferencesHelper(mPreferencesHelper);
2232 
2233         mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
2234         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2235         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2236 
2237         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2238                 captor.getValue().getAction());
2239         assertEquals(PKG, captor.getValue().getPackage());
2240         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2241     }
2242 
2243     @Test
testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()2244     public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
2245         mService.setPreferencesHelper(mPreferencesHelper);
2246 
2247         mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
2248         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2249     }
2250 
2251     @Test
testUpdateAppNotifyCreatorUnblock()2252     public void testUpdateAppNotifyCreatorUnblock() throws Exception {
2253         mService.setPreferencesHelper(mPreferencesHelper);
2254 
2255         mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
2256         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2257         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2258 
2259         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2260                 captor.getValue().getAction());
2261         assertEquals(PKG, captor.getValue().getPackage());
2262         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2263     }
2264 
2265     @Test
testUpdateChannelNotifyCreatorBlock()2266     public void testUpdateChannelNotifyCreatorBlock() throws Exception {
2267         mService.setPreferencesHelper(mPreferencesHelper);
2268         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2269                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2270                 .thenReturn(mTestNotificationChannel);
2271 
2272         NotificationChannel updatedChannel =
2273                 new NotificationChannel(mTestNotificationChannel.getId(),
2274                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
2275 
2276         mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
2277         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2278         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2279 
2280         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2281                 captor.getValue().getAction());
2282         assertEquals(PKG, captor.getValue().getPackage());
2283         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
2284                         NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
2285         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2286     }
2287 
2288     @Test
testUpdateChannelNotifyCreatorUnblock()2289     public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
2290         NotificationChannel existingChannel =
2291                 new NotificationChannel(mTestNotificationChannel.getId(),
2292                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
2293         mService.setPreferencesHelper(mPreferencesHelper);
2294         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2295                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2296                 .thenReturn(existingChannel);
2297 
2298         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2299         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2300         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2301 
2302         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2303                 captor.getValue().getAction());
2304         assertEquals(PKG, captor.getValue().getPackage());
2305         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
2306                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
2307         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2308     }
2309 
2310     @Test
testUpdateChannelNoNotifyCreatorOtherChanges()2311     public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
2312         NotificationChannel existingChannel =
2313                 new NotificationChannel(mTestNotificationChannel.getId(),
2314                         mTestNotificationChannel.getName(), IMPORTANCE_MAX);
2315         mService.setPreferencesHelper(mPreferencesHelper);
2316         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2317                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2318                 .thenReturn(existingChannel);
2319 
2320         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2321         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2322     }
2323 
2324     @Test
testUpdateGroupNotifyCreatorBlock()2325     public void testUpdateGroupNotifyCreatorBlock() throws Exception {
2326         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2327         mService.setPreferencesHelper(mPreferencesHelper);
2328         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2329                 eq(PKG), anyInt()))
2330                 .thenReturn(existing);
2331 
2332         NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
2333         updated.setBlocked(true);
2334 
2335         mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
2336         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2337         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2338 
2339         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2340                 captor.getValue().getAction());
2341         assertEquals(PKG, captor.getValue().getPackage());
2342         assertEquals(existing.getId(), captor.getValue().getStringExtra(
2343                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
2344         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2345     }
2346 
2347     @Test
testUpdateGroupNotifyCreatorUnblock()2348     public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
2349         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2350         existing.setBlocked(true);
2351         mService.setPreferencesHelper(mPreferencesHelper);
2352         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2353                 eq(PKG), anyInt()))
2354                 .thenReturn(existing);
2355 
2356         mBinderService.updateNotificationChannelGroupForPackage(
2357                 PKG, 0, new NotificationChannelGroup("id", "name"));
2358         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2359         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2360 
2361         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2362                 captor.getValue().getAction());
2363         assertEquals(PKG, captor.getValue().getPackage());
2364         assertEquals(existing.getId(), captor.getValue().getStringExtra(
2365                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
2366         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2367     }
2368 
2369     @Test
testUpdateGroupNoNotifyCreatorOtherChanges()2370     public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
2371         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2372         mService.setPreferencesHelper(mPreferencesHelper);
2373         when(mPreferencesHelper.getNotificationChannelGroup(
2374                 eq(existing.getId()), eq(PKG), anyInt()))
2375                 .thenReturn(existing);
2376 
2377         mBinderService.updateNotificationChannelGroupForPackage(
2378                 PKG, 0, new NotificationChannelGroup("id", "new name"));
2379         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2380     }
2381 
2382     @Test
testCreateChannelNotifyListener()2383     public void testCreateChannelNotifyListener() throws Exception {
2384         List<String> associations = new ArrayList<>();
2385         associations.add("a");
2386         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2387                 .thenReturn(associations);
2388         mService.setPreferencesHelper(mPreferencesHelper);
2389         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2390                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2391                 .thenReturn(mTestNotificationChannel);
2392         NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
2393         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2394                 eq(channel2.getId()), anyBoolean()))
2395                 .thenReturn(channel2);
2396         when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
2397                 eq(channel2), anyBoolean(), anyBoolean()))
2398                 .thenReturn(true);
2399 
2400         reset(mListeners);
2401         mBinderService.createNotificationChannels(PKG,
2402                 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
2403         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
2404                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2405                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2406         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
2407                 eq(Process.myUserHandle()), eq(channel2),
2408                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2409     }
2410 
2411     @Test
testCreateChannelGroupNotifyListener()2412     public void testCreateChannelGroupNotifyListener() throws Exception {
2413         List<String> associations = new ArrayList<>();
2414         associations.add("a");
2415         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2416                 .thenReturn(associations);
2417         mService.setPreferencesHelper(mPreferencesHelper);
2418         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
2419         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
2420 
2421         reset(mListeners);
2422         mBinderService.createNotificationChannelGroups(PKG,
2423                 new ParceledListSlice(Arrays.asList(group1, group2)));
2424         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
2425                 eq(Process.myUserHandle()), eq(group1),
2426                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2427         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
2428                 eq(Process.myUserHandle()), eq(group2),
2429                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2430     }
2431 
2432     @Test
testUpdateChannelNotifyListener()2433     public void testUpdateChannelNotifyListener() throws Exception {
2434         List<String> associations = new ArrayList<>();
2435         associations.add("a");
2436         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2437                 .thenReturn(associations);
2438         mService.setPreferencesHelper(mPreferencesHelper);
2439         mTestNotificationChannel.setLightColor(Color.CYAN);
2440         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2441                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2442                 .thenReturn(mTestNotificationChannel);
2443 
2444         reset(mListeners);
2445         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2446         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
2447                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2448                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2449     }
2450 
2451     @Test
testDeleteChannelNotifyListener()2452     public void testDeleteChannelNotifyListener() throws Exception {
2453         List<String> associations = new ArrayList<>();
2454         associations.add("a");
2455         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2456                 .thenReturn(associations);
2457         mService.setPreferencesHelper(mPreferencesHelper);
2458         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2459                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2460                 .thenReturn(mTestNotificationChannel);
2461         reset(mListeners);
2462         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
2463         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
2464                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2465                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2466     }
2467 
2468     @Test
testDeleteChannelGroupNotifyListener()2469     public void testDeleteChannelGroupNotifyListener() throws Exception {
2470         List<String> associations = new ArrayList<>();
2471         associations.add("a");
2472         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2473                 .thenReturn(associations);
2474         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
2475         mService.setPreferencesHelper(mPreferencesHelper);
2476         when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
2477                 .thenReturn(ncg);
2478         reset(mListeners);
2479         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
2480         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
2481                 eq(Process.myUserHandle()), eq(ncg),
2482                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2483     }
2484 
2485     @Test
testUpdateNotificationChannelFromPrivilegedListener_success()2486     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
2487         mService.setPreferencesHelper(mPreferencesHelper);
2488         List<String> associations = new ArrayList<>();
2489         associations.add("a");
2490         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2491                 .thenReturn(associations);
2492         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
2493                 eq(mTestNotificationChannel.getId()), anyBoolean()))
2494                 .thenReturn(mTestNotificationChannel);
2495 
2496         mBinderService.updateNotificationChannelFromPrivilegedListener(
2497                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
2498 
2499         verify(mPreferencesHelper, times(1)).updateNotificationChannel(
2500                 anyString(), anyInt(), any(), anyBoolean());
2501 
2502         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
2503                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2504                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2505     }
2506 
2507     @Test
testUpdateNotificationChannelFromPrivilegedListener_noAccess()2508     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
2509         mService.setPreferencesHelper(mPreferencesHelper);
2510         List<String> associations = new ArrayList<>();
2511         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2512                 .thenReturn(associations);
2513 
2514         try {
2515             mBinderService.updateNotificationChannelFromPrivilegedListener(
2516                     null, PKG, Process.myUserHandle(), mTestNotificationChannel);
2517             fail("listeners that don't have a companion device shouldn't be able to call this");
2518         } catch (SecurityException e) {
2519             // pass
2520         }
2521 
2522         verify(mPreferencesHelper, never()).updateNotificationChannel(
2523                 anyString(), anyInt(), any(), anyBoolean());
2524 
2525         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
2526                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2527                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2528     }
2529 
2530     @Test
testUpdateNotificationChannelFromPrivilegedListener_badUser()2531     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
2532         mService.setPreferencesHelper(mPreferencesHelper);
2533         List<String> associations = new ArrayList<>();
2534         associations.add("a");
2535         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2536                 .thenReturn(associations);
2537         mListener = mock(ManagedServices.ManagedServiceInfo.class);
2538         mListener.component = new ComponentName(PKG, PKG);
2539         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
2540         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
2541 
2542         try {
2543             mBinderService.updateNotificationChannelFromPrivilegedListener(
2544                     null, PKG, UserHandle.ALL, mTestNotificationChannel);
2545             fail("incorrectly allowed a change to a user listener cannot see");
2546         } catch (SecurityException e) {
2547             // pass
2548         }
2549 
2550         verify(mPreferencesHelper, never()).updateNotificationChannel(
2551                 anyString(), anyInt(), any(), anyBoolean());
2552 
2553         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
2554                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2555                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2556     }
2557 
2558     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_success()2559     public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
2560         mService.setPreferencesHelper(mPreferencesHelper);
2561         List<String> associations = new ArrayList<>();
2562         associations.add("a");
2563         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2564                 .thenReturn(associations);
2565 
2566         mBinderService.getNotificationChannelsFromPrivilegedListener(
2567                 null, PKG, Process.myUserHandle());
2568 
2569         verify(mPreferencesHelper, times(1)).getNotificationChannels(
2570                 anyString(), anyInt(), anyBoolean());
2571     }
2572 
2573     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()2574     public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
2575         mService.setPreferencesHelper(mPreferencesHelper);
2576         List<String> associations = new ArrayList<>();
2577         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2578                 .thenReturn(associations);
2579 
2580         try {
2581             mBinderService.getNotificationChannelsFromPrivilegedListener(
2582                     null, PKG, Process.myUserHandle());
2583             fail("listeners that don't have a companion device shouldn't be able to call this");
2584         } catch (SecurityException e) {
2585             // pass
2586         }
2587 
2588         verify(mPreferencesHelper, never()).getNotificationChannels(
2589                 anyString(), anyInt(), anyBoolean());
2590     }
2591 
2592     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_success()2593     public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2594             throws Exception {
2595         mService.setPreferencesHelper(mPreferencesHelper);
2596         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2597                 .thenReturn(new ArrayList<>());
2598         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2599 
2600         mBinderService.getNotificationChannelsFromPrivilegedListener(
2601                 null, PKG, Process.myUserHandle());
2602 
2603         verify(mPreferencesHelper, times(1)).getNotificationChannels(
2604                 anyString(), anyInt(), anyBoolean());
2605     }
2606 
2607     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()2608     public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2609             throws Exception {
2610         mService.setPreferencesHelper(mPreferencesHelper);
2611         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2612                 .thenReturn(new ArrayList<>());
2613         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2614 
2615         try {
2616             mBinderService.getNotificationChannelsFromPrivilegedListener(
2617                     null, PKG, Process.myUserHandle());
2618             fail("listeners that don't have a companion device shouldn't be able to call this");
2619         } catch (SecurityException e) {
2620             // pass
2621         }
2622 
2623         verify(mPreferencesHelper, never()).getNotificationChannels(
2624                 anyString(), anyInt(), anyBoolean());
2625     }
2626 
2627     @Test
testGetNotificationChannelFromPrivilegedListener_badUser()2628     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
2629         mService.setPreferencesHelper(mPreferencesHelper);
2630         List<String> associations = new ArrayList<>();
2631         associations.add("a");
2632         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2633                 .thenReturn(associations);
2634         mListener = mock(ManagedServices.ManagedServiceInfo.class);
2635         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
2636         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
2637 
2638         try {
2639             mBinderService.getNotificationChannelsFromPrivilegedListener(
2640                     null, PKG, Process.myUserHandle());
2641             fail("listener getting channels from a user they cannot see");
2642         } catch (SecurityException e) {
2643             // pass
2644         }
2645 
2646         verify(mPreferencesHelper, never()).getNotificationChannels(
2647                 anyString(), anyInt(), anyBoolean());
2648     }
2649 
2650     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_success()2651     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
2652         mService.setPreferencesHelper(mPreferencesHelper);
2653         List<String> associations = new ArrayList<>();
2654         associations.add("a");
2655         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2656                 .thenReturn(associations);
2657 
2658         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2659                 null, PKG, Process.myUserHandle());
2660 
2661         verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
2662     }
2663 
2664     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()2665     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
2666         mService.setPreferencesHelper(mPreferencesHelper);
2667         List<String> associations = new ArrayList<>();
2668         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2669                 .thenReturn(associations);
2670 
2671         try {
2672             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2673                     null, PKG, Process.myUserHandle());
2674             fail("listeners that don't have a companion device shouldn't be able to call this");
2675         } catch (SecurityException e) {
2676             // pass
2677         }
2678 
2679         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
2680     }
2681 
2682     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_badUser()2683     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
2684         mService.setPreferencesHelper(mPreferencesHelper);
2685         List<String> associations = new ArrayList<>();
2686         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2687                 .thenReturn(associations);
2688         mListener = mock(ManagedServices.ManagedServiceInfo.class);
2689         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
2690         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
2691         try {
2692             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2693                     null, PKG, Process.myUserHandle());
2694             fail("listeners that don't have a companion device shouldn't be able to call this");
2695         } catch (SecurityException e) {
2696             // pass
2697         }
2698 
2699         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
2700     }
2701 
2702     @Test
testHasCompanionDevice_failure()2703     public void testHasCompanionDevice_failure() throws Exception {
2704         when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2705                 new IllegalArgumentException());
2706         mService.hasCompanionDevice(mListener);
2707     }
2708 
2709     @Test
testHasCompanionDevice_noService()2710     public void testHasCompanionDevice_noService() {
2711         mService =
2712                 new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
2713                 mSystemClock, mNotificationInstanceIdSequence);
2714 
2715         assertFalse(mService.hasCompanionDevice(mListener));
2716     }
2717 
2718     @Test
testSnoozeRunnable_reSnoozeASingleSnoozedNotification()2719     public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2720         final NotificationRecord notification = generateNotificationRecord(
2721                 mTestNotificationChannel, 1, null, true);
2722         mService.addNotification(notification);
2723         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2724 
2725         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2726                 mService.new SnoozeNotificationRunnable(
2727                 notification.getKey(), 100, null);
2728         snoozeNotificationRunnable.run();
2729         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2730                 mService.new SnoozeNotificationRunnable(
2731                 notification.getKey(), 100, null);
2732         snoozeNotificationRunnable.run();
2733 
2734         // snooze twice
2735         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2736     }
2737 
2738     @Test
testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey()2739     public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2740         final NotificationRecord notification = generateNotificationRecord(
2741                 mTestNotificationChannel, 1, "group", true);
2742         mService.addNotification(notification);
2743         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2744 
2745         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2746                 mService.new SnoozeNotificationRunnable(
2747                 notification.getKey(), 100, null);
2748         snoozeNotificationRunnable.run();
2749         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2750                 mService.new SnoozeNotificationRunnable(
2751                 notification.getKey(), 100, null);
2752         snoozeNotificationRunnable.run();
2753 
2754         // snooze twice
2755         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2756     }
2757 
2758     @Test
testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey()2759     public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2760         final NotificationRecord notification = generateNotificationRecord(
2761                 mTestNotificationChannel, 1, "group", true);
2762         final NotificationRecord notification2 = generateNotificationRecord(
2763                 mTestNotificationChannel, 2, "group", true);
2764         mService.addNotification(notification);
2765         mService.addNotification(notification2);
2766         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2767         when(mSnoozeHelper.getNotifications(
2768                 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2769 
2770         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2771                 mService.new SnoozeNotificationRunnable(
2772                         notification.getKey(), 100, null);
2773         snoozeNotificationRunnable.run();
2774         when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2775                 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2776         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2777                 mService.new SnoozeNotificationRunnable(
2778                         notification.getKey(), 100, null);
2779         snoozeNotificationRunnable.run();
2780 
2781         // snooze twice
2782         verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2783     }
2784 
2785     @Test
testSnoozeRunnable_snoozeNonGrouped()2786     public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2787         final NotificationRecord nonGrouped = generateNotificationRecord(
2788                 mTestNotificationChannel, 1, null, false);
2789         final NotificationRecord grouped = generateNotificationRecord(
2790                 mTestNotificationChannel, 2, "group", false);
2791         mService.addNotification(grouped);
2792         mService.addNotification(nonGrouped);
2793 
2794         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2795                 mService.new SnoozeNotificationRunnable(
2796                         nonGrouped.getKey(), 100, null);
2797         snoozeNotificationRunnable.run();
2798 
2799         // only snooze the one notification
2800         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2801         assertTrue(nonGrouped.getStats().hasSnoozed());
2802 
2803         assertEquals(2, mNotificationRecordLogger.numCalls());
2804         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2805                 mNotificationRecordLogger.event(0));
2806         assertEquals(
2807                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2808                 mNotificationRecordLogger.event(1));
2809     }
2810 
2811     @Test
testSnoozeRunnable_snoozeSummary_withChildren()2812     public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2813         final NotificationRecord parent = generateNotificationRecord(
2814                 mTestNotificationChannel, 1, "group", true);
2815         final NotificationRecord child = generateNotificationRecord(
2816                 mTestNotificationChannel, 2, "group", false);
2817         final NotificationRecord child2 = generateNotificationRecord(
2818                 mTestNotificationChannel, 3, "group", false);
2819         mService.addNotification(parent);
2820         mService.addNotification(child);
2821         mService.addNotification(child2);
2822 
2823         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2824                 mService.new SnoozeNotificationRunnable(
2825                         parent.getKey(), 100, null);
2826         snoozeNotificationRunnable.run();
2827 
2828         // snooze parent and children
2829         verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2830     }
2831 
2832     @Test
testSnoozeRunnable_snoozeGroupChild_fellowChildren()2833     public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2834         final NotificationRecord parent = generateNotificationRecord(
2835                 mTestNotificationChannel, 1, "group", true);
2836         final NotificationRecord child = generateNotificationRecord(
2837                 mTestNotificationChannel, 2, "group", false);
2838         final NotificationRecord child2 = generateNotificationRecord(
2839                 mTestNotificationChannel, 3, "group", false);
2840         mService.addNotification(parent);
2841         mService.addNotification(child);
2842         mService.addNotification(child2);
2843 
2844         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2845                 mService.new SnoozeNotificationRunnable(
2846                         child2.getKey(), 100, null);
2847         snoozeNotificationRunnable.run();
2848 
2849         // only snooze the one child
2850         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2851 
2852         assertEquals(2, mNotificationRecordLogger.numCalls());
2853         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2854                 mNotificationRecordLogger.event(0));
2855         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
2856                         .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
2857     }
2858 
2859     @Test
testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()2860     public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2861         final NotificationRecord parent = generateNotificationRecord(
2862                 mTestNotificationChannel, 1, "group", true);
2863         assertTrue(parent.getSbn().getNotification().isGroupSummary());
2864         final NotificationRecord child = generateNotificationRecord(
2865                 mTestNotificationChannel, 2, "group", false);
2866         mService.addNotification(parent);
2867         mService.addNotification(child);
2868 
2869         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2870                 mService.new SnoozeNotificationRunnable(
2871                         child.getKey(), 100, null);
2872         snoozeNotificationRunnable.run();
2873 
2874         // snooze child and summary
2875         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2876 
2877         assertEquals(4, mNotificationRecordLogger.numCalls());
2878         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2879                 mNotificationRecordLogger.event(0));
2880         assertEquals(
2881                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2882                 mNotificationRecordLogger.event(1));
2883         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2884                 mNotificationRecordLogger.event(2));
2885         assertEquals(
2886                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2887                 mNotificationRecordLogger.event(3));
2888     }
2889 
2890     @Test
testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()2891     public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2892         final NotificationRecord child = generateNotificationRecord(
2893                 mTestNotificationChannel, 2, "group", false);
2894         mService.addNotification(child);
2895 
2896         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2897                 mService.new SnoozeNotificationRunnable(
2898                         child.getKey(), 100, null);
2899         snoozeNotificationRunnable.run();
2900 
2901         // snooze child only
2902         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2903 
2904         assertEquals(2, mNotificationRecordLogger.numCalls());
2905         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2906                 mNotificationRecordLogger.event(0));
2907         assertEquals(
2908                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2909                 mNotificationRecordLogger.event(1));
2910     }
2911 
2912     @Test
testPostGroupChild_unsnoozeParent()2913     public void testPostGroupChild_unsnoozeParent() throws Exception {
2914         final NotificationRecord child = generateNotificationRecord(
2915                 mTestNotificationChannel, 2, "group", false);
2916 
2917         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
2918                 child.getSbn().getId(), child.getSbn().getNotification(),
2919                 child.getSbn().getUserId());
2920         waitForIdle();
2921 
2922         verify(mSnoozeHelper, times(1)).repostGroupSummary(
2923                 anyString(), anyInt(), eq(child.getGroupKey()));
2924     }
2925 
2926     @Test
testPostNonGroup_noUnsnoozing()2927     public void testPostNonGroup_noUnsnoozing() throws Exception {
2928         final NotificationRecord record = generateNotificationRecord(
2929                 mTestNotificationChannel, 2, null, false);
2930 
2931         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
2932                 record.getSbn().getId(), record.getSbn().getNotification(),
2933                 record.getSbn().getUserId());
2934         waitForIdle();
2935 
2936         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2937     }
2938 
2939     @Test
testPostGroupSummary_noUnsnoozing()2940     public void testPostGroupSummary_noUnsnoozing() throws Exception {
2941         final NotificationRecord parent = generateNotificationRecord(
2942                 mTestNotificationChannel, 2, "group", true);
2943 
2944         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
2945                 parent.getSbn().getId(), parent.getSbn().getNotification(),
2946                 parent.getSbn().getUserId());
2947         waitForIdle();
2948 
2949         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2950     }
2951 
2952     @Test
testSystemNotificationListenerCanUnsnooze()2953     public void testSystemNotificationListenerCanUnsnooze() throws Exception {
2954         final NotificationRecord nr = generateNotificationRecord(
2955                 mTestNotificationChannel, 2, "group", false);
2956 
2957         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2958                 "testSystemNotificationListenerCanUnsnooze",
2959                 nr.getSbn().getId(), nr.getSbn().getNotification(),
2960                 nr.getSbn().getUserId());
2961         waitForIdle();
2962         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2963                 mService.new SnoozeNotificationRunnable(
2964                         nr.getKey(), 100, null);
2965         snoozeNotificationRunnable.run();
2966 
2967         ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
2968                 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
2969         listener.isSystem = true;
2970         when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
2971 
2972         mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
2973         waitForIdle();
2974         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
2975         assertEquals(1, notifs.length);
2976         assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
2977     }
2978 
2979     @Test
testSetListenerAccessForUser()2980     public void testSetListenerAccessForUser() throws Exception {
2981         UserHandle user = UserHandle.of(10);
2982         ComponentName c = ComponentName.unflattenFromString("package/Component");
2983         mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2984 
2985 
2986         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2987         verify(mListeners, times(1)).setPackageOrComponentEnabled(
2988                 c.flattenToString(), user.getIdentifier(), true, true);
2989         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2990                 c.flattenToString(), user.getIdentifier(), false, true);
2991         verify(mAssistants, never()).setPackageOrComponentEnabled(
2992                 any(), anyInt(), anyBoolean(), anyBoolean());
2993     }
2994 
2995     @Test
testSetAssistantAccessForUser()2996     public void testSetAssistantAccessForUser() throws Exception {
2997         UserHandle user = UserHandle.of(10);
2998         List<UserInfo> uis = new ArrayList<>();
2999         UserInfo ui = new UserInfo();
3000         ui.id = 10;
3001         uis.add(ui);
3002         ComponentName c = ComponentName.unflattenFromString("package/Component");
3003         when(mUm.getEnabledProfiles(10)).thenReturn(uis);
3004 
3005         mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
3006 
3007         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
3008         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3009                 c.flattenToString(), user.getIdentifier(), true, true);
3010         verify(mAssistants).setUserSet(10, true);
3011         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3012                 c.flattenToString(), user.getIdentifier(), false, true);
3013         verify(mListeners, never()).setPackageOrComponentEnabled(
3014                 any(), anyInt(), anyBoolean(), anyBoolean());
3015     }
3016 
3017     @Test
testGetAssistantAllowedForUser()3018     public void testGetAssistantAllowedForUser() throws Exception {
3019         UserHandle user = UserHandle.of(10);
3020         try {
3021             mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
3022         } catch (IllegalStateException e) {
3023             if (!e.getMessage().contains("At most one NotificationAssistant")) {
3024                 throw e;
3025             }
3026         }
3027         verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
3028     }
3029 
3030     @Test
testGetAssistantAllowed()3031     public void testGetAssistantAllowed() throws Exception {
3032         try {
3033             mBinderService.getAllowedNotificationAssistant();
3034         } catch (IllegalStateException e) {
3035             if (!e.getMessage().contains("At most one NotificationAssistant")) {
3036                 throw e;
3037             }
3038         }
3039         verify(mAssistants, times(1)).getAllowedComponents(0);
3040     }
3041 
3042     @Test
testSetDndAccessForUser()3043     public void testSetDndAccessForUser() throws Exception {
3044         UserHandle user = UserHandle.of(10);
3045         ComponentName c = ComponentName.unflattenFromString("package/Component");
3046         mBinderService.setNotificationPolicyAccessGrantedForUser(
3047                 c.getPackageName(), user.getIdentifier(), true);
3048 
3049         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
3050         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3051                 c.getPackageName(), user.getIdentifier(), true, true);
3052         verify(mAssistants, never()).setPackageOrComponentEnabled(
3053                 any(), anyInt(), anyBoolean(), anyBoolean());
3054         verify(mListeners, never()).setPackageOrComponentEnabled(
3055                 any(), anyInt(), anyBoolean(), anyBoolean());
3056     }
3057 
3058     @Test
testSetListenerAccess()3059     public void testSetListenerAccess() throws Exception {
3060         ComponentName c = ComponentName.unflattenFromString("package/Component");
3061         mBinderService.setNotificationListenerAccessGranted(c, true);
3062 
3063         verify(mListeners, times(1)).setPackageOrComponentEnabled(
3064                 c.flattenToString(), 0, true, true);
3065         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3066                 c.flattenToString(), 0, false, true);
3067         verify(mAssistants, never()).setPackageOrComponentEnabled(
3068                 any(), anyInt(), anyBoolean(), anyBoolean());
3069     }
3070 
3071     @Test
testSetAssistantAccess()3072     public void testSetAssistantAccess() throws Exception {
3073         List<UserInfo> uis = new ArrayList<>();
3074         UserInfo ui = new UserInfo();
3075         ui.id = 0;
3076         uis.add(ui);
3077         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3078         ComponentName c = ComponentName.unflattenFromString("package/Component");
3079 
3080         mBinderService.setNotificationAssistantAccessGranted(c, true);
3081 
3082         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3083                 c.flattenToString(), 0, true, true);
3084         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3085                 c.flattenToString(), 0, false, true);
3086         verify(mListeners, never()).setPackageOrComponentEnabled(
3087                 any(), anyInt(), anyBoolean(), anyBoolean());
3088     }
3089 
3090     @Test
testSetAssistantAccess_multiProfile()3091     public void testSetAssistantAccess_multiProfile() throws Exception {
3092         List<UserInfo> uis = new ArrayList<>();
3093         UserInfo ui = new UserInfo();
3094         ui.id = 0;
3095         uis.add(ui);
3096         UserInfo ui10 = new UserInfo();
3097         ui10.id = 10;
3098         uis.add(ui10);
3099         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3100         ComponentName c = ComponentName.unflattenFromString("package/Component");
3101 
3102         mBinderService.setNotificationAssistantAccessGranted(c, true);
3103 
3104         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3105                 c.flattenToString(), 0, true, true);
3106         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3107                 c.flattenToString(), 10, true, true);
3108         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3109                 c.flattenToString(), 0, false, true);
3110         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3111                 c.flattenToString(), 10, false, true);
3112         verify(mListeners, never()).setPackageOrComponentEnabled(
3113                 any(), anyInt(), anyBoolean(), anyBoolean());
3114     }
3115 
3116     @Test
testSetAssistantAccess_nullWithAllowedAssistant()3117     public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
3118         ArrayList<ComponentName> componentList = new ArrayList<>();
3119         ComponentName c = ComponentName.unflattenFromString("package/Component");
3120         componentList.add(c);
3121         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
3122         List<UserInfo> uis = new ArrayList<>();
3123         UserInfo ui = new UserInfo();
3124         ui.id = 0;
3125         uis.add(ui);
3126         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3127 
3128         mBinderService.setNotificationAssistantAccessGranted(null, true);
3129 
3130         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3131                 c.flattenToString(), 0, true, false);
3132         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3133                 c.flattenToString(), 0, false,  false);
3134         verify(mListeners, never()).setPackageOrComponentEnabled(
3135                 any(), anyInt(), anyBoolean(), anyBoolean());
3136     }
3137 
3138     @Test
testSetAssistantAccessForUser_nullWithAllowedAssistant()3139     public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
3140         List<UserInfo> uis = new ArrayList<>();
3141         UserInfo ui = new UserInfo();
3142         ui.id = 10;
3143         uis.add(ui);
3144         UserHandle user = ui.getUserHandle();
3145         ArrayList<ComponentName> componentList = new ArrayList<>();
3146         ComponentName c = ComponentName.unflattenFromString("package/Component");
3147         componentList.add(c);
3148         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
3149         when(mUm.getEnabledProfiles(10)).thenReturn(uis);
3150 
3151         mBinderService.setNotificationAssistantAccessGrantedForUser(
3152                 null, user.getIdentifier(), true);
3153 
3154         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3155                 c.flattenToString(), user.getIdentifier(), true, false);
3156         verify(mAssistants).setUserSet(10, true);
3157         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3158                 c.flattenToString(), user.getIdentifier(), false,  false);
3159         verify(mListeners, never()).setPackageOrComponentEnabled(
3160                 any(), anyInt(), anyBoolean(), anyBoolean());
3161     }
3162 
3163     @Test
testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()3164     public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
3165             throws Exception {
3166         List<UserInfo> uis = new ArrayList<>();
3167         UserInfo ui = new UserInfo();
3168         ui.id = 0;
3169         uis.add(ui);
3170         UserInfo ui10 = new UserInfo();
3171         ui10.id = 10;
3172         uis.add(ui10);
3173         UserHandle user = ui.getUserHandle();
3174         ArrayList<ComponentName> componentList = new ArrayList<>();
3175         ComponentName c = ComponentName.unflattenFromString("package/Component");
3176         componentList.add(c);
3177         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
3178         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3179 
3180         mBinderService.setNotificationAssistantAccessGrantedForUser(
3181                     null, user.getIdentifier(), true);
3182 
3183         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3184                 c.flattenToString(), user.getIdentifier(), true, false);
3185         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3186                 c.flattenToString(), ui10.id, true, false);
3187         verify(mAssistants).setUserSet(0, true);
3188         verify(mAssistants).setUserSet(10, true);
3189         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3190                 c.flattenToString(), user.getIdentifier(), false,  false);
3191         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3192                 c.flattenToString(), ui10.id, false,  false);
3193         verify(mListeners, never()).setPackageOrComponentEnabled(
3194                 any(), anyInt(), anyBoolean(), anyBoolean());
3195     }
3196 
3197     @Test
testSetDndAccess()3198     public void testSetDndAccess() throws Exception {
3199         ComponentName c = ComponentName.unflattenFromString("package/Component");
3200 
3201         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3202 
3203         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3204                 c.getPackageName(), 0, true, true);
3205         verify(mAssistants, never()).setPackageOrComponentEnabled(
3206                 any(), anyInt(), anyBoolean(), anyBoolean());
3207         verify(mListeners, never()).setPackageOrComponentEnabled(
3208                 any(), anyInt(), anyBoolean(), anyBoolean());
3209     }
3210 
3211     @Test
testSetListenerAccess_onLowRam()3212     public void testSetListenerAccess_onLowRam() throws Exception {
3213         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3214         ComponentName c = ComponentName.unflattenFromString("package/Component");
3215         mBinderService.setNotificationListenerAccessGranted(c, true);
3216 
3217         verify(mListeners).setPackageOrComponentEnabled(
3218                 anyString(), anyInt(), anyBoolean(), anyBoolean());
3219         verify(mConditionProviders).setPackageOrComponentEnabled(
3220                 anyString(), anyInt(), anyBoolean(), anyBoolean());
3221         verify(mAssistants).migrateToXml();
3222         verify(mAssistants).resetDefaultAssistantsIfNecessary();
3223     }
3224 
3225     @Test
testSetAssistantAccess_onLowRam()3226     public void testSetAssistantAccess_onLowRam() throws Exception {
3227         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3228         ComponentName c = ComponentName.unflattenFromString("package/Component");
3229         List<UserInfo> uis = new ArrayList<>();
3230         UserInfo ui = new UserInfo();
3231         ui.id = 0;
3232         uis.add(ui);
3233         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3234 
3235         mBinderService.setNotificationAssistantAccessGranted(c, true);
3236 
3237         verify(mListeners).migrateToXml();
3238         verify(mConditionProviders).setPackageOrComponentEnabled(
3239                 anyString(), anyInt(), anyBoolean(), anyBoolean());
3240         verify(mAssistants).migrateToXml();
3241         verify(mAssistants).resetDefaultAssistantsIfNecessary();
3242     }
3243 
3244     @Test
testSetDndAccess_onLowRam()3245     public void testSetDndAccess_onLowRam() throws Exception {
3246         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3247         ComponentName c = ComponentName.unflattenFromString("package/Component");
3248         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3249 
3250         verify(mListeners).migrateToXml();
3251         verify(mConditionProviders).setPackageOrComponentEnabled(
3252                 anyString(), anyInt(), anyBoolean(), anyBoolean());
3253         verify(mAssistants).migrateToXml();
3254         verify(mAssistants).resetDefaultAssistantsIfNecessary();
3255     }
3256 
3257     @Test
testSetListenerAccess_doesNothingOnLowRam_exceptWatch()3258     public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3259         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3260         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3261         ComponentName c = ComponentName.unflattenFromString("package/Component");
3262 
3263         mBinderService.setNotificationListenerAccessGranted(c, true);
3264 
3265         verify(mListeners, times(1)).setPackageOrComponentEnabled(
3266                 c.flattenToString(), 0, true, true);
3267         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3268                 c.flattenToString(), 0, false, true);
3269         verify(mAssistants, never()).setPackageOrComponentEnabled(
3270                 any(), anyInt(), anyBoolean(), anyBoolean());
3271     }
3272 
3273     @Test
testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()3274     public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3275         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3276         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3277         ComponentName c = ComponentName.unflattenFromString("package/Component");
3278         List<UserInfo> uis = new ArrayList<>();
3279         UserInfo ui = new UserInfo();
3280         ui.id = 0;
3281         uis.add(ui);
3282         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3283 
3284         mBinderService.setNotificationAssistantAccessGranted(c, true);
3285 
3286         verify(mListeners, never()).setPackageOrComponentEnabled(
3287                 anyString(), anyInt(), anyBoolean(), anyBoolean());
3288         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3289                 c.flattenToString(), 0, false, true);
3290         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3291                 c.flattenToString(), 0, true, true);
3292     }
3293 
3294     @Test
testSetDndAccess_doesNothingOnLowRam_exceptWatch()3295     public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3296         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3297         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3298         ComponentName c = ComponentName.unflattenFromString("package/Component");
3299 
3300         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3301 
3302         verify(mListeners, never()).setPackageOrComponentEnabled(
3303                 anyString(), anyInt(), anyBoolean(), anyBoolean());
3304         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3305                 c.getPackageName(), 0, true, true);
3306         verify(mAssistants, never()).setPackageOrComponentEnabled(
3307                 any(), anyInt(), anyBoolean(), anyBoolean());
3308     }
3309 
3310     @Test
testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups()3311     public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
3312         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3313         mService.addEnqueuedNotification(r);
3314         NotificationManagerService.PostNotificationRunnable runnable =
3315                 mService.new PostNotificationRunnable(r.getKey());
3316         runnable.run();
3317         waitForIdle();
3318 
3319         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
3320     }
3321 
3322     @Test
testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()3323     public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
3324             throws Exception {
3325         NotificationRecord r =
3326                 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
3327         mService.addNotification(r);
3328 
3329         r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3330         mService.addEnqueuedNotification(r);
3331         NotificationManagerService.PostNotificationRunnable runnable =
3332                 mService.new PostNotificationRunnable(r.getKey());
3333         runnable.run();
3334         waitForIdle();
3335 
3336         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
3337     }
3338 
3339     @Test
testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()3340     public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
3341             throws Exception {
3342         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
3343                 false);
3344         mService.addNotification(r);
3345         mService.addEnqueuedNotification(r);
3346 
3347         NotificationManagerService.PostNotificationRunnable runnable =
3348                 mService.new PostNotificationRunnable(r.getKey());
3349         runnable.run();
3350         waitForIdle();
3351 
3352         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
3353     }
3354 
3355     @Test
testDontAutogroupIfCritical()3356     public void testDontAutogroupIfCritical() throws Exception {
3357         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3358         r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
3359         mService.addEnqueuedNotification(r);
3360         NotificationManagerService.PostNotificationRunnable runnable =
3361                 mService.new PostNotificationRunnable(r.getKey());
3362         runnable.run();
3363 
3364         r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
3365         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
3366         runnable = mService.new PostNotificationRunnable(r.getKey());
3367         mService.addEnqueuedNotification(r);
3368 
3369         runnable.run();
3370         waitForIdle();
3371 
3372         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
3373     }
3374 
3375     @Test
testNoFakeColorizedPermission()3376     public void testNoFakeColorizedPermission() throws Exception {
3377         when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
3378         Notification.Builder nb = new Notification.Builder(mContext,
3379                 mTestNotificationChannel.getId())
3380                 .setContentTitle("foo")
3381                 .setColorized(true)
3382                 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
3383                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
3384         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
3385                 "testNoFakeColorizedPermission", mUid, 0,
3386                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
3387         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3388 
3389         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
3390                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
3391         waitForIdle();
3392 
3393         NotificationRecord posted = mService.findNotificationLocked(
3394                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
3395 
3396         assertFalse(posted.getNotification().isColorized());
3397     }
3398 
3399     @Test
testGetNotificationCountLocked()3400     public void testGetNotificationCountLocked() {
3401         String sampleTagToExclude = null;
3402         int sampleIdToExclude = 0;
3403         for (int i = 0; i < 20; i++) {
3404             NotificationRecord r =
3405                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
3406             mService.addEnqueuedNotification(r);
3407 
3408         }
3409         for (int i = 0; i < 20; i++) {
3410             NotificationRecord r =
3411                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
3412             mService.addNotification(r);
3413             sampleTagToExclude = r.getSbn().getTag();
3414             sampleIdToExclude = i;
3415         }
3416 
3417         // another package
3418         Notification n =
3419                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
3420                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3421                 .build();
3422 
3423         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
3424                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
3425         NotificationRecord otherPackage =
3426                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3427         mService.addEnqueuedNotification(otherPackage);
3428         mService.addNotification(otherPackage);
3429 
3430         // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
3431         // anything that's currently enqueued or posted
3432         int userId = UserHandle.getUserId(mUid);
3433         assertEquals(40,
3434                 mService.getNotificationCountLocked(PKG, userId, 0, null));
3435         assertEquals(40,
3436                 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
3437 
3438         // return all for package "a" - "banana" tag isn't used
3439         assertEquals(2,
3440                 mService.getNotificationCountLocked("a", userId, 0, "banana"));
3441 
3442         // exclude a known notification - it's excluded from only the posted list, not enqueued
3443         assertEquals(39, mService.getNotificationCountLocked(
3444                 PKG, userId, sampleIdToExclude, sampleTagToExclude));
3445     }
3446 
3447     @Test
testAddAutogroup_requestsSort()3448     public void testAddAutogroup_requestsSort() throws Exception {
3449         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3450         mService.addNotification(r);
3451         mService.addAutogroupKeyLocked(r.getKey());
3452 
3453         verify(mRankingHandler, times(1)).requestSort();
3454     }
3455 
3456     @Test
testRemoveAutogroup_requestsSort()3457     public void testRemoveAutogroup_requestsSort() throws Exception {
3458         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3459         r.setOverrideGroupKey("TEST");
3460         mService.addNotification(r);
3461         mService.removeAutogroupKeyLocked(r.getKey());
3462 
3463         verify(mRankingHandler, times(1)).requestSort();
3464     }
3465 
3466     @Test
testReaddAutogroup_noSort()3467     public void testReaddAutogroup_noSort() throws Exception {
3468         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3469         r.setOverrideGroupKey("TEST");
3470         mService.addNotification(r);
3471         mService.addAutogroupKeyLocked(r.getKey());
3472 
3473         verify(mRankingHandler, never()).requestSort();
3474     }
3475 
3476     @Test
testHandleRankingSort_sendsUpdateOnSignalExtractorChange()3477     public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
3478         mService.setPreferencesHelper(mPreferencesHelper);
3479         NotificationManagerService.WorkerHandler handler = mock(
3480                 NotificationManagerService.WorkerHandler.class);
3481         mService.setHandler(handler);
3482 
3483         Map<String, Answer> answers = getSignalExtractorSideEffects();
3484         for (String message : answers.keySet()) {
3485             mService.clearNotifications();
3486             final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3487             mService.addNotification(r);
3488 
3489             doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
3490 
3491             mService.handleRankingSort();
3492         }
3493         verify(handler, times(answers.size())).scheduleSendRankingUpdate();
3494     }
3495 
3496     @Test
testHandleRankingSort_noUpdateWhenNoSignalChange()3497     public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
3498         mService.setRankingHelper(mRankingHelper);
3499         NotificationManagerService.WorkerHandler handler = mock(
3500                 NotificationManagerService.WorkerHandler.class);
3501         mService.setHandler(handler);
3502 
3503         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3504         mService.addNotification(r);
3505 
3506         mService.handleRankingSort();
3507         verify(handler, never()).scheduleSendRankingUpdate();
3508     }
3509 
3510     @Test
testReadPolicyXml_readApprovedServicesFromXml()3511     public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
3512         final String upgradeXml = "<notification-policy version=\"1\">"
3513                 + "<ranking></ranking>"
3514                 + "<enabled_listeners>"
3515                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3516                 + "</enabled_listeners>"
3517                 + "<enabled_assistants>"
3518                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3519                 + "</enabled_assistants>"
3520                 + "<dnd_apps>"
3521                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3522                 + "</dnd_apps>"
3523                 + "</notification-policy>";
3524         mService.readPolicyXml(
3525                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3526                 false,
3527                 UserHandle.USER_ALL);
3528         verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3529         verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3530         verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3531 
3532         // numbers are inflated for setup
3533         verify(mListeners, times(1)).migrateToXml();
3534         verify(mConditionProviders, times(1)).migrateToXml();
3535         verify(mAssistants, times(1)).migrateToXml();
3536         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
3537     }
3538 
3539     @Test
testReadPolicyXml_readSnoozedNotificationsFromXml()3540     public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
3541         final String upgradeXml = "<notification-policy version=\"1\">"
3542                 + "<snoozed-notifications>></snoozed-notifications>"
3543                 + "</notification-policy>";
3544         mService.readPolicyXml(
3545                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3546                 false,
3547                 UserHandle.USER_ALL);
3548         verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong());
3549     }
3550 
3551     @Test
testReadPolicyXml_readApprovedServicesFromSettings()3552     public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
3553         final String preupgradeXml = "<notification-policy version=\"1\">"
3554                 + "<ranking></ranking>"
3555                 + "</notification-policy>";
3556         mService.readPolicyXml(
3557                 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
3558                 false,
3559                 UserHandle.USER_ALL);
3560         verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
3561         verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
3562         verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
3563 
3564         // numbers are inflated for setup
3565         verify(mListeners, times(2)).migrateToXml();
3566         verify(mConditionProviders, times(2)).migrateToXml();
3567         verify(mAssistants, times(2)).migrateToXml();
3568         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
3569     }
3570 
3571     @Test
testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()3572     public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3573         final String policyXml = "<notification-policy version=\"1\">"
3574                 + "<ranking></ranking>"
3575                 + "<enabled_listeners>"
3576                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3577                 + "</enabled_listeners>"
3578                 + "<enabled_assistants>"
3579                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3580                 + "</enabled_assistants>"
3581                 + "<dnd_apps>"
3582                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3583                 + "</dnd_apps>"
3584                 + "</notification-policy>";
3585         when(mUm.isManagedProfile(10)).thenReturn(true);
3586         mService.readPolicyXml(
3587                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3588                 true,
3589                 10);
3590         verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3591         verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3592         verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3593     }
3594 
3595     @Test
testReadPolicyXml_restoresManagedServicesForNonManagedUser()3596     public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3597         final String policyXml = "<notification-policy version=\"1\">"
3598                 + "<ranking></ranking>"
3599                 + "<enabled_listeners>"
3600                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3601                 + "</enabled_listeners>"
3602                 + "<enabled_assistants>"
3603                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3604                 + "</enabled_assistants>"
3605                 + "<dnd_apps>"
3606                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3607                 + "</dnd_apps>"
3608                 + "</notification-policy>";
3609         when(mUm.isManagedProfile(10)).thenReturn(false);
3610         mService.readPolicyXml(
3611                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3612                 true,
3613                 10);
3614         verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3615         verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3616         verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3617     }
3618 
3619     @Test
testLocaleChangedCallsUpdateDefaultZenModeRules()3620     public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3621         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3622         mService.mZenModeHelper = mZenModeHelper;
3623         mService.mLocaleChangeReceiver.onReceive(mContext,
3624                 new Intent(Intent.ACTION_LOCALE_CHANGED));
3625 
3626         verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3627     }
3628 
3629     @Test
testBumpFGImportance_noChannelChangePreOApp()3630     public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
3631         String preOPkg = PKG_N_MR1;
3632         final ApplicationInfo legacy = new ApplicationInfo();
3633         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3634         when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3635                 .thenReturn(legacy);
3636         when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3637                 .thenReturn(Binder.getCallingUid());
3638         getContext().setMockPackageManager(mPackageManagerClient);
3639 
3640         Notification.Builder nb = new Notification.Builder(mContext,
3641                 NotificationChannel.DEFAULT_CHANNEL_ID)
3642                 .setContentTitle("foo")
3643                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3644                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3645                 .setPriority(Notification.PRIORITY_MIN);
3646 
3647         StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3648                 "testBumpFGImportance_noChannelChangePreOApp",
3649                 Binder.getCallingUid(), 0, nb.build(),
3650                 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
3651 
3652         mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3653                 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
3654         waitForIdle();
3655 
3656         assertEquals(IMPORTANCE_LOW,
3657                 mService.getNotificationRecord(sbn.getKey()).getImportance());
3658 
3659         nb = new Notification.Builder(mContext)
3660                 .setContentTitle("foo")
3661                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3662                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3663                 .setPriority(Notification.PRIORITY_MIN);
3664 
3665         sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3666                 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
3667                 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
3668 
3669         mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3670                 "testBumpFGImportance_noChannelChangePreOApp",
3671                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3672         waitForIdle();
3673         assertEquals(IMPORTANCE_LOW,
3674                 mService.getNotificationRecord(sbn.getKey()).getImportance());
3675 
3676         NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
3677                 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
3678         assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3679     }
3680 
3681     @Test
testStats_updatedOnDirectReply()3682     public void testStats_updatedOnDirectReply() throws Exception {
3683         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3684         mService.addNotification(r);
3685 
3686         mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3687         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
3688         verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.getSbn()));
3689 
3690         assertEquals(1, mNotificationRecordLogger.numCalls());
3691         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
3692                 mNotificationRecordLogger.event(0));
3693     }
3694 
3695     @Test
testStats_updatedOnUserExpansion()3696     public void testStats_updatedOnUserExpansion() throws Exception {
3697         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3698         mService.addNotification(r);
3699 
3700         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3701                 NOTIFICATION_LOCATION_UNKNOWN);
3702         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3703                 eq((true)));
3704         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3705 
3706         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3707                 NOTIFICATION_LOCATION_UNKNOWN);
3708         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3709                 eq((false)));
3710         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3711 
3712         assertEquals(2, mNotificationRecordLogger.numCalls());
3713         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
3714                 mNotificationRecordLogger.event(0));
3715         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
3716                 mNotificationRecordLogger.event(1));
3717     }
3718 
3719     @Test
testStats_notUpdatedOnAutoExpansion()3720     public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3721         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3722         mService.addNotification(r);
3723 
3724         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3725                 NOTIFICATION_LOCATION_UNKNOWN);
3726         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3727         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(false),
3728                 eq((true)));
3729 
3730         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3731                 NOTIFICATION_LOCATION_UNKNOWN);
3732         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3733         verify(mAssistants).notifyAssistantExpansionChangedLocked(
3734                 eq(r.getSbn()), eq(false), eq((false)));
3735     }
3736 
3737     @Test
testStats_updatedOnViewSettings()3738     public void testStats_updatedOnViewSettings() throws Exception {
3739         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3740         mService.addNotification(r);
3741 
3742         mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3743         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3744     }
3745 
3746     @Test
testStats_updatedOnVisibilityChanged()3747     public void testStats_updatedOnVisibilityChanged() throws Exception {
3748         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3749         mService.addNotification(r);
3750 
3751         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
3752         mService.mNotificationDelegate.onNotificationVisibilityChanged(
3753                 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
3754         verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(true));
3755         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3756         mService.mNotificationDelegate.onNotificationVisibilityChanged(
3757                 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
3758         verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(false));
3759         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3760     }
3761 
3762     @Test
testStats_dismissalSurface()3763     public void testStats_dismissalSurface() throws Exception {
3764         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3765         r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
3766         mService.addNotification(r);
3767 
3768         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
3769         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3770                 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3771                 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
3772         waitForIdle();
3773 
3774         assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
3775 
3776         // Using mService.addNotification() does not generate a NotificationRecordLogger log,
3777         // so we only get the cancel notification.
3778         assertEquals(1, mNotificationRecordLogger.numCalls());
3779 
3780         assertEquals(
3781                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
3782                 mNotificationRecordLogger.event(0));
3783         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
3784     }
3785 
3786     @Test
testStats_dismissalSentiment()3787     public void testStats_dismissalSentiment() throws Exception {
3788         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3789         mService.addNotification(r);
3790 
3791         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
3792         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3793                 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3794                 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3795         waitForIdle();
3796 
3797         assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3798                 r.getStats().getDismissalSentiment());
3799     }
3800 
3801     @Test
testApplyAdjustmentMultiUser()3802     public void testApplyAdjustmentMultiUser() throws Exception {
3803         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3804         mService.addNotification(r);
3805         NotificationManagerService.WorkerHandler handler = mock(
3806                 NotificationManagerService.WorkerHandler.class);
3807         mService.setHandler(handler);
3808 
3809         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3810 
3811         Bundle signals = new Bundle();
3812         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3813                 USER_SENTIMENT_NEGATIVE);
3814         Adjustment adjustment = new Adjustment(
3815                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3816         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3817 
3818         waitForIdle();
3819 
3820         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3821     }
3822 
3823     @Test
testAssistantBlockingTriggersCancel()3824     public void testAssistantBlockingTriggersCancel() throws Exception {
3825         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3826         mService.addNotification(r);
3827         NotificationManagerService.WorkerHandler handler = mock(
3828                 NotificationManagerService.WorkerHandler.class);
3829         mService.setHandler(handler);
3830 
3831         Bundle signals = new Bundle();
3832         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
3833         Adjustment adjustment = new Adjustment(
3834                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3835         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3836         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3837 
3838         waitForIdle();
3839 
3840         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3841         verify(handler, times(1)).scheduleCancelNotification(any());
3842     }
3843 
3844     @Test
testApplyEnqueuedAdjustmentFromAssistant_singleUser()3845     public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3846         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3847         mService.addEnqueuedNotification(r);
3848         NotificationManagerService.WorkerHandler handler = mock(
3849                 NotificationManagerService.WorkerHandler.class);
3850         mService.setHandler(handler);
3851         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3852 
3853         Bundle signals = new Bundle();
3854         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3855                 USER_SENTIMENT_NEGATIVE);
3856         Adjustment adjustment = new Adjustment(
3857                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3858         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3859 
3860         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3861     }
3862 
3863     @Test
testApplyEnqueuedAdjustmentFromAssistant_importance()3864     public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
3865         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3866         mService.addEnqueuedNotification(r);
3867         NotificationManagerService.WorkerHandler handler = mock(
3868                 NotificationManagerService.WorkerHandler.class);
3869         mService.setHandler(handler);
3870         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3871 
3872         Bundle signals = new Bundle();
3873         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
3874         Adjustment adjustment = new Adjustment(
3875                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3876         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3877 
3878         assertEquals(IMPORTANCE_LOW, r.getImportance());
3879     }
3880 
3881     @Test
testApplyEnqueuedAdjustmentFromAssistant_crossUser()3882     public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3883         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3884         mService.addEnqueuedNotification(r);
3885         NotificationManagerService.WorkerHandler handler = mock(
3886                 NotificationManagerService.WorkerHandler.class);
3887         mService.setHandler(handler);
3888         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3889 
3890         Bundle signals = new Bundle();
3891         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3892                 USER_SENTIMENT_NEGATIVE);
3893         Adjustment adjustment = new Adjustment(
3894                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3895         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3896 
3897         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3898 
3899         waitForIdle();
3900 
3901         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3902     }
3903 
3904     @Test
testUserSentimentChangeTriggersUpdate()3905     public void testUserSentimentChangeTriggersUpdate() throws Exception {
3906         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3907         mService.addNotification(r);
3908         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3909 
3910         Bundle signals = new Bundle();
3911         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3912                 USER_SENTIMENT_NEGATIVE);
3913         Adjustment adjustment = new Adjustment(
3914                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3915         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3916 
3917         waitForIdle();
3918 
3919         verify(mRankingHandler, timeout(300).times(1)).requestSort();
3920     }
3921 
3922     @Test
testTooLateAdjustmentTriggersUpdate()3923     public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3924         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3925         mService.addNotification(r);
3926         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3927 
3928         Bundle signals = new Bundle();
3929         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3930                 USER_SENTIMENT_NEGATIVE);
3931         Adjustment adjustment = new Adjustment(
3932                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3933         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3934 
3935         waitForIdle();
3936 
3937         verify(mRankingHandler, times(1)).requestSort();
3938     }
3939 
3940     @Test
testEnqueuedAdjustmentAppliesAdjustments()3941     public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3942         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3943         mService.addEnqueuedNotification(r);
3944         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3945 
3946         Bundle signals = new Bundle();
3947         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3948                 USER_SENTIMENT_NEGATIVE);
3949         Adjustment adjustment = new Adjustment(
3950                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3951         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3952 
3953         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3954     }
3955 
3956     @Test
testRestore()3957     public void testRestore() throws Exception {
3958         int systemChecks = mService.countSystemChecks;
3959         mBinderService.applyRestore(null, USER_SYSTEM);
3960         assertEquals(1, mService.countSystemChecks - systemChecks);
3961     }
3962 
3963     @Test
testBackupEmptySound()3964     public void testBackupEmptySound() throws Exception {
3965         NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3966         channel.setSound(Uri.EMPTY, null);
3967 
3968         XmlSerializer serializer = new FastXmlSerializer();
3969         ByteArrayOutputStream baos = new ByteArrayOutputStream();
3970         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3971         channel.writeXmlForBackup(serializer, getContext());
3972 
3973         XmlPullParser parser = Xml.newPullParser();
3974         parser.setInput(new BufferedInputStream(
3975                 new ByteArrayInputStream(baos.toByteArray())), null);
3976         NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3977         restored.populateFromXmlForRestore(parser, getContext());
3978 
3979         assertNull(restored.getSound());
3980     }
3981 
3982     @Test
testBackup()3983     public void testBackup() throws Exception {
3984         int systemChecks = mService.countSystemChecks;
3985         when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3986                 .thenReturn(new ArraySet<>());
3987         mBinderService.getBackupPayload(1);
3988         assertEquals(1, mService.countSystemChecks - systemChecks);
3989     }
3990 
3991     @Test
testEmptyVibration_noException()3992     public void testEmptyVibration_noException() throws Exception {
3993         NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3994         channel.setVibrationPattern(new long[0]);
3995 
3996         XmlSerializer serializer = new FastXmlSerializer();
3997         ByteArrayOutputStream baos = new ByteArrayOutputStream();
3998         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3999         channel.writeXml(serializer);
4000     }
4001 
4002     @Test
updateUriPermissions_update()4003     public void updateUriPermissions_update() throws Exception {
4004         NotificationChannel c = new NotificationChannel(
4005                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
4006         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
4007         Message message1 = new Message("", 0, "");
4008         message1.setData("",
4009                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
4010         Message message2 = new Message("", 1, "");
4011         message2.setData("",
4012                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
4013 
4014         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
4015                 .setContentTitle("foo")
4016                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4017                 .setStyle(new Notification.MessagingStyle("")
4018                         .addMessage(message1)
4019                         .addMessage(message2));
4020         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
4021                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
4022                 null, 0), c);
4023 
4024         // First post means we grant access to both
4025         reset(mUgm);
4026         reset(mUgmInternal);
4027         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
4028         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
4029                 USER_SYSTEM);
4030         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
4031                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
4032         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
4033                 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
4034 
4035         Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
4036                 .setContentTitle("foo")
4037                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4038                 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
4039         NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
4040                 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
4041                 c);
4042 
4043         // Update means we drop access to first
4044         reset(mUgmInternal);
4045         mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
4046                 USER_SYSTEM);
4047         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
4048                 eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1));
4049 
4050         // Update back means we grant access to first again
4051         reset(mUgm);
4052         mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
4053                 USER_SYSTEM);
4054         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
4055                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
4056 
4057         // And update to empty means we drop everything
4058         reset(mUgmInternal);
4059         mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
4060                 USER_SYSTEM);
4061         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
4062                 anyInt(), anyInt());
4063     }
4064 
4065     @Test
updateUriPermissions_posterDoesNotOwnUri()4066     public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
4067         NotificationChannel c = new NotificationChannel(
4068                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
4069         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
4070         Message message1 = new Message("", 0, "");
4071         message1.setData("",
4072                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
4073 
4074         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
4075                 .setContentTitle("foo")
4076                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4077                 .setStyle(new Notification.MessagingStyle("")
4078                         .addMessage(message1));
4079         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
4080                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
4081                 null, 0), c);
4082 
4083         doThrow(new SecurityException("no access")).when(mUgm)
4084                 .grantUriPermissionFromOwner(
4085                         any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
4086 
4087         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
4088         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),  USER_SYSTEM);
4089 
4090         // yay, no crash
4091     }
4092 
4093     @Test
testVisitUris()4094     public void testVisitUris() throws Exception {
4095         final Uri audioContents = Uri.parse("content://com.example/audio");
4096         final Uri backgroundImage = Uri.parse("content://com.example/background");
4097 
4098         Bundle extras = new Bundle();
4099         extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
4100         extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
4101 
4102         Notification n = new Notification.Builder(mContext, "a")
4103                 .setContentTitle("notification with uris")
4104                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4105                 .addExtras(extras)
4106                 .build();
4107 
4108         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
4109         n.visitUris(visitor);
4110         verify(visitor, times(1)).accept(eq(audioContents));
4111         verify(visitor, times(1)).accept(eq(backgroundImage));
4112     }
4113 
4114     @Test
testSetNotificationPolicy_preP_setOldFields()4115     public void testSetNotificationPolicy_preP_setOldFields() {
4116         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4117         mService.mZenModeHelper = mZenModeHelper;
4118         NotificationManager.Policy userPolicy =
4119                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4120         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4121 
4122         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4123                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
4124 
4125         int expected = SUPPRESSED_EFFECT_BADGE
4126                 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
4127                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
4128                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4129         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
4130 
4131         assertEquals(expected, actual);
4132     }
4133 
4134     @Test
testSetNotificationPolicy_preP_setNewFields()4135     public void testSetNotificationPolicy_preP_setNewFields() {
4136         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4137         mService.mZenModeHelper = mZenModeHelper;
4138         NotificationManager.Policy userPolicy =
4139                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4140         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4141 
4142         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4143                 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
4144 
4145         int expected = SUPPRESSED_EFFECT_BADGE;
4146         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
4147 
4148         assertEquals(expected, actual);
4149     }
4150 
4151     @Test
testSetNotificationPolicy_preP_setOldNewFields()4152     public void testSetNotificationPolicy_preP_setOldNewFields() {
4153         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4154         mService.mZenModeHelper = mZenModeHelper;
4155         NotificationManager.Policy userPolicy =
4156                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4157         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4158 
4159         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4160                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
4161 
4162         int expected =
4163                 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
4164         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
4165 
4166         assertEquals(expected, actual);
4167     }
4168 
4169     @Test
testSetNotificationPolicy_P_setOldFields()4170     public void testSetNotificationPolicy_P_setOldFields() {
4171         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4172         mService.mZenModeHelper = mZenModeHelper;
4173         NotificationManager.Policy userPolicy =
4174                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4175         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4176 
4177         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4178                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
4179 
4180         int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
4181                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
4182                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4183         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4184 
4185         assertEquals(expected, actual);
4186     }
4187 
4188     @Test
testSetNotificationPolicy_P_setNewFields()4189     public void testSetNotificationPolicy_P_setNewFields() {
4190         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4191         mService.mZenModeHelper = mZenModeHelper;
4192         NotificationManager.Policy userPolicy =
4193                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4194         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4195 
4196         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4197                 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
4198                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4199 
4200         int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
4201                 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
4202                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4203         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4204 
4205         assertEquals(expected, actual);
4206     }
4207 
4208     @Test
testSetNotificationPolicy_P_setOldNewFields()4209     public void testSetNotificationPolicy_P_setOldNewFields() {
4210         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4211         mService.mZenModeHelper = mZenModeHelper;
4212         NotificationManager.Policy userPolicy =
4213                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4214         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4215 
4216         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4217                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
4218 
4219         int expected =  SUPPRESSED_EFFECT_STATUS_BAR;
4220         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4221 
4222         assertEquals(expected, actual);
4223 
4224         appPolicy = new NotificationManager.Policy(0, 0, 0,
4225                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
4226                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4227 
4228         expected =  SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
4229                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4230         actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4231 
4232         assertEquals(expected, actual);
4233     }
4234 
4235     @Test
testVisualDifference_foreground()4236     public void testVisualDifference_foreground() {
4237         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4238                 .setContentTitle("foo");
4239         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4240                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4241         NotificationRecord r1 =
4242                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4243 
4244         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4245                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
4246                 .setContentTitle("bar");
4247         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4248                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4249         NotificationRecord r2 =
4250                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4251 
4252         assertFalse(mService.isVisuallyInterruptive(r1, r2));
4253     }
4254 
4255     @Test
testVisualDifference_diffTitle()4256     public void testVisualDifference_diffTitle() {
4257         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4258                 .setContentTitle("foo");
4259         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4260                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4261         NotificationRecord r1 =
4262                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4263 
4264         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4265                 .setContentTitle("bar");
4266         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4267                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4268         NotificationRecord r2 =
4269                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4270 
4271         assertTrue(mService.isVisuallyInterruptive(r1, r2));
4272     }
4273 
4274     @Test
testVisualDifference_inboxStyle()4275     public void testVisualDifference_inboxStyle() {
4276         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4277                 .setStyle(new Notification.InboxStyle()
4278                     .addLine("line1").addLine("line2"));
4279         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4280                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4281         NotificationRecord r1 =
4282                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4283 
4284         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4285                 .setStyle(new Notification.InboxStyle()
4286                         .addLine("line1").addLine("line2_changed"));
4287         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4288                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4289         NotificationRecord r2 =
4290                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4291 
4292         assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
4293 
4294         Notification.Builder nb3 = new Notification.Builder(mContext, "")
4295                 .setStyle(new Notification.InboxStyle()
4296                         .addLine("line1"));
4297         StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4298                 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4299         NotificationRecord r3 =
4300                 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
4301 
4302         assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
4303 
4304         Notification.Builder nb4 = new Notification.Builder(mContext, "")
4305                 .setStyle(new Notification.InboxStyle()
4306                         .addLine("line1").addLine("line2").addLine("line3"));
4307         StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4308                 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4309         NotificationRecord r4 =
4310                 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
4311 
4312         assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
4313 
4314         Notification.Builder nb5 = new Notification.Builder(mContext, "")
4315             .setContentText("not an inbox");
4316         StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4317                 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4318         NotificationRecord r5 =
4319                 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
4320 
4321         assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
4322     }
4323 
4324     @Test
testVisualDifference_diffText()4325     public void testVisualDifference_diffText() {
4326         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4327                 .setContentText("foo");
4328         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4329                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4330         NotificationRecord r1 =
4331                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4332 
4333         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4334                 .setContentText("bar");
4335         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4336                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4337         NotificationRecord r2 =
4338                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4339 
4340         assertTrue(mService.isVisuallyInterruptive(r1, r2));
4341     }
4342 
4343     @Test
testVisualDifference_sameText()4344     public void testVisualDifference_sameText() {
4345         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4346                 .setContentText("foo");
4347         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4348                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4349         NotificationRecord r1 =
4350                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4351 
4352         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4353                 .setContentText("foo");
4354         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4355                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4356         NotificationRecord r2 =
4357                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4358 
4359         assertFalse(mService.isVisuallyInterruptive(r1, r2));
4360     }
4361 
4362     @Test
testVisualDifference_sameTextButStyled()4363     public void testVisualDifference_sameTextButStyled() {
4364         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4365                 .setContentText(Html.fromHtml("<b>foo</b>"));
4366         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4367                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4368         NotificationRecord r1 =
4369                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4370 
4371         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4372                 .setContentText(Html.fromHtml("<b>foo</b>"));
4373         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4374                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4375         NotificationRecord r2 =
4376                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4377 
4378         assertFalse(mService.isVisuallyInterruptive(r1, r2));
4379     }
4380 
4381     @Test
testVisualDifference_diffTextButStyled()4382     public void testVisualDifference_diffTextButStyled() {
4383         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4384                 .setContentText(Html.fromHtml("<b>foo</b>"));
4385         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4386                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4387         NotificationRecord r1 =
4388                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4389 
4390         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4391                 .setContentText(Html.fromHtml("<b>bar</b>"));
4392         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4393                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4394         NotificationRecord r2 =
4395                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4396 
4397         assertTrue(mService.isVisuallyInterruptive(r1, r2));
4398     }
4399 
4400     @Test
testVisualDifference_diffProgress()4401     public void testVisualDifference_diffProgress() {
4402         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4403                 .setProgress(100, 90, false);
4404         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4405                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4406         NotificationRecord r1 =
4407                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4408 
4409         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4410                 .setProgress(100, 100, false);
4411         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4412                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4413         NotificationRecord r2 =
4414                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4415 
4416         assertTrue(mService.isVisuallyInterruptive(r1, r2));
4417     }
4418 
4419     @Test
testVisualDifference_diffProgressNotDone()4420     public void testVisualDifference_diffProgressNotDone() {
4421         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4422                 .setProgress(100, 90, false);
4423         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4424                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4425         NotificationRecord r1 =
4426                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4427 
4428         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4429                 .setProgress(100, 91, false);
4430         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4431                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4432         NotificationRecord r2 =
4433                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4434 
4435         assertFalse(mService.isVisuallyInterruptive(r1, r2));
4436     }
4437 
4438     @Test
testVisualDifference_sameProgressStillDone()4439     public void testVisualDifference_sameProgressStillDone() {
4440         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4441                 .setProgress(100, 100, false);
4442         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4443                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4444         NotificationRecord r1 =
4445                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4446 
4447         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4448                 .setProgress(100, 100, false);
4449         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4450                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4451         NotificationRecord r2 =
4452                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4453 
4454         assertFalse(mService.isVisuallyInterruptive(r1, r2));
4455     }
4456 
4457     @Test
testVisualDifference_summary()4458     public void testVisualDifference_summary() {
4459         Notification.Builder nb1 = new Notification.Builder(mContext, "")
4460                 .setGroup("bananas")
4461                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4462                 .setContentText("foo");
4463         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4464                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4465         NotificationRecord r1 =
4466                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4467 
4468         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4469                 .setGroup("bananas")
4470                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4471                 .setContentText("bar");
4472         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4473                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4474         NotificationRecord r2 =
4475                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4476 
4477         assertFalse(mService.isVisuallyInterruptive(r1, r2));
4478     }
4479 
4480     @Test
testVisualDifference_summaryNewNotification()4481     public void testVisualDifference_summaryNewNotification() {
4482         Notification.Builder nb2 = new Notification.Builder(mContext, "")
4483                 .setGroup("bananas")
4484                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4485                 .setContentText("bar");
4486         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4487                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4488         NotificationRecord r2 =
4489                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4490 
4491         assertFalse(mService.isVisuallyInterruptive(null, r2));
4492     }
4493 
4494     @Test
testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()4495     public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
4496         // post 2 notification from this package
4497         final NotificationRecord notif1 = generateNotificationRecord(
4498                 mTestNotificationChannel, 1, null, true);
4499         final NotificationRecord notif2 = generateNotificationRecord(
4500                 mTestNotificationChannel, 2, null, false);
4501         mService.addNotification(notif1);
4502         mService.addNotification(notif2);
4503 
4504         // on broadcast, hide the 2 notifications
4505         mService.simulatePackageSuspendBroadcast(true, PKG);
4506         ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
4507         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4508         assertEquals(2, captorHide.getValue().size());
4509 
4510         // on broadcast, unhide the 2 notifications
4511         mService.simulatePackageSuspendBroadcast(false, PKG);
4512         ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
4513         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4514         assertEquals(2, captorUnhide.getValue().size());
4515     }
4516 
4517     @Test
testNoNotificationsHiddenOnSuspendedPackageBroadcast()4518     public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
4519         // post 2 notification from this package
4520         final NotificationRecord notif1 = generateNotificationRecord(
4521                 mTestNotificationChannel, 1, null, true);
4522         final NotificationRecord notif2 = generateNotificationRecord(
4523                 mTestNotificationChannel, 2, null, false);
4524         mService.addNotification(notif1);
4525         mService.addNotification(notif2);
4526 
4527         // on broadcast, nothing is hidden since no notifications are of package "test_package"
4528         mService.simulatePackageSuspendBroadcast(true, "test_package");
4529         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4530         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4531         assertEquals(0, captor.getValue().size());
4532     }
4533 
4534     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast()4535     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
4536         // Post 2 notifications from 2 packages
4537         NotificationRecord pkgA = new NotificationRecord(mContext,
4538                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4539         mService.addNotification(pkgA);
4540         NotificationRecord pkgB = new NotificationRecord(mContext,
4541                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4542         mService.addNotification(pkgB);
4543 
4544         // on broadcast, hide one of the packages
4545         mService.simulatePackageDistractionBroadcast(
4546                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
4547         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4548         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4549         assertEquals(1, captorHide.getValue().size());
4550         assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
4551 
4552         // on broadcast, unhide the package
4553         mService.simulatePackageDistractionBroadcast(
4554                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
4555         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4556         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4557         assertEquals(1, captorUnhide.getValue().size());
4558         assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
4559     }
4560 
4561     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()4562     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
4563         // Post 2 notifications from 2 packages
4564         NotificationRecord pkgA = new NotificationRecord(mContext,
4565                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4566         mService.addNotification(pkgA);
4567         NotificationRecord pkgB = new NotificationRecord(mContext,
4568                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4569         mService.addNotification(pkgB);
4570 
4571         // on broadcast, hide one of the packages
4572         mService.simulatePackageDistractionBroadcast(
4573                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
4574         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4575 
4576         // should be called only once.
4577         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4578         assertEquals(2, captorHide.getValue().size());
4579         assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
4580         assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
4581 
4582         // on broadcast, unhide the package
4583         mService.simulatePackageDistractionBroadcast(
4584                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
4585         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4586 
4587         // should be called only once.
4588         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4589         assertEquals(2, captorUnhide.getValue().size());
4590         assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
4591         assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
4592     }
4593 
4594     @Test
testNoNotificationsHiddenOnDistractingPackageBroadcast()4595     public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
4596         // post notification from this package
4597         final NotificationRecord notif1 = generateNotificationRecord(
4598                 mTestNotificationChannel, 1, null, true);
4599         mService.addNotification(notif1);
4600 
4601         // on broadcast, nothing is hidden since no notifications are of package "test_package"
4602         mService.simulatePackageDistractionBroadcast(
4603                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
4604         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4605         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4606         assertEquals(0, captor.getValue().size());
4607     }
4608 
4609     @Test
testCanUseManagedServicesNullPkg()4610     public void testCanUseManagedServicesNullPkg() {
4611         assertEquals(true, mService.canUseManagedServices(null, 0, null));
4612     }
4613 
4614 
4615     @Test
testCanUseManagedServicesNoValidPkg()4616     public void testCanUseManagedServicesNoValidPkg() {
4617         assertEquals(true, mService.canUseManagedServices("d", 0, null));
4618     }
4619 
4620     @Test
testCanUseManagedServices_hasPermission()4621     public void testCanUseManagedServices_hasPermission() throws Exception {
4622         when(mPackageManager.checkPermission("perm", "pkg", 0))
4623                 .thenReturn(PackageManager.PERMISSION_GRANTED);
4624 
4625         assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4626     }
4627 
4628     @Test
testCanUseManagedServices_noPermission()4629     public void testCanUseManagedServices_noPermission() throws Exception {
4630         when(mPackageManager.checkPermission("perm", "pkg", 0))
4631                 .thenReturn(PackageManager.PERMISSION_DENIED);
4632 
4633         assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4634     }
4635 
4636     @Test
testCanUseManagedServices_permDoesNotMatter()4637     public void testCanUseManagedServices_permDoesNotMatter() {
4638         assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
4639     }
4640 
4641     @Test
testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()4642     public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4643         final NotificationRecord r = generateNotificationRecord(
4644                 mTestNotificationChannel, 1, null, true);
4645         r.setTextChanged(true);
4646         mService.addNotification(r);
4647 
4648         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4649                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4650                 new NotificationVisibility[]{});
4651 
4652         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4653     }
4654 
4655     @Test
testOnNotificationVisibilityChanged_triggersVisibilityLog()4656     public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
4657         final NotificationRecord r = generateNotificationRecord(
4658                 mTestNotificationChannel, 1, null, true);
4659         r.setTextChanged(true);
4660         r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
4661         mService.addNotification(r);
4662 
4663         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4664                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4665                 new NotificationVisibility[]{});
4666 
4667         assertEquals(1, mNotificationRecordLogger.numCalls());
4668         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
4669                 mNotificationRecordLogger.event(0));
4670         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
4671 
4672         mService.mNotificationDelegate.onNotificationVisibilityChanged(
4673                 new NotificationVisibility[]{},
4674                 new NotificationVisibility[]
4675                         {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
4676         );
4677 
4678         assertEquals(2, mNotificationRecordLogger.numCalls());
4679         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
4680                 mNotificationRecordLogger.event(1));
4681         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
4682     }
4683 
4684     @Test
testSetNotificationsShownFromListener_triggersInterruptionUsageStat()4685     public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4686             throws RemoteException {
4687         final NotificationRecord r = generateNotificationRecord(
4688                 mTestNotificationChannel, 1, null, true);
4689         r.setTextChanged(true);
4690         mService.addNotification(r);
4691 
4692         mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4693 
4694         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4695     }
4696 
4697     @Test
testMaybeRecordInterruptionLocked_doesNotRecordTwice()4698     public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
4699             throws RemoteException {
4700         final NotificationRecord r = generateNotificationRecord(
4701                 mTestNotificationChannel, 1, null, true);
4702         r.setInterruptive(true);
4703         mService.addNotification(r);
4704 
4705         mService.maybeRecordInterruptionLocked(r);
4706         mService.maybeRecordInterruptionLocked(r);
4707 
4708         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4709                 anyString(), anyString(), anyInt());
4710         verify(mHistoryManager, times(1)).addNotification(any());
4711     }
4712 
4713     @Test
testBubble()4714     public void testBubble() throws Exception {
4715         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4716         assertFalse(mBinderService.areBubblesAllowed(PKG));
4717         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4718                 BUBBLE_PREFERENCE_NONE);
4719     }
4720 
4721     @Test
testUserApprovedBubblesForPackageSelected()4722     public void testUserApprovedBubblesForPackageSelected() throws Exception {
4723         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
4724         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4725                 BUBBLE_PREFERENCE_SELECTED);
4726     }
4727 
4728     @Test
testUserApprovedBubblesForPackageAll()4729     public void testUserApprovedBubblesForPackageAll() throws Exception {
4730         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
4731         assertTrue(mBinderService.areBubblesAllowed(PKG));
4732         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4733                 BUBBLE_PREFERENCE_ALL);
4734     }
4735 
4736     @Test
testUserRejectsBubblesForPackage()4737     public void testUserRejectsBubblesForPackage() throws Exception {
4738         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4739         assertFalse(mBinderService.areBubblesAllowed(PKG));
4740     }
4741 
4742     @Test
testIsCallerInstantApp_primaryUser()4743     public void testIsCallerInstantApp_primaryUser() throws Exception {
4744         ApplicationInfo info = new ApplicationInfo();
4745         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4746         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
4747         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4748 
4749         assertTrue(mService.isCallerInstantApp(45770, 0));
4750 
4751         info.privateFlags = 0;
4752         assertFalse(mService.isCallerInstantApp(575370, 0));
4753     }
4754 
4755     @Test
testIsCallerInstantApp_secondaryUser()4756     public void testIsCallerInstantApp_secondaryUser() throws Exception {
4757         ApplicationInfo info = new ApplicationInfo();
4758         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4759         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4760         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4761         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4762 
4763         assertTrue(mService.isCallerInstantApp(68638450, 10));
4764     }
4765 
4766     @Test
testIsCallerInstantApp_userAllNotification()4767     public void testIsCallerInstantApp_userAllNotification() throws Exception {
4768         ApplicationInfo info = new ApplicationInfo();
4769         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4770         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
4771                 .thenReturn(info);
4772         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4773 
4774         assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4775 
4776         info.privateFlags = 0;
4777         assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4778     }
4779 
4780     @Test
testResolveNotificationUid_sameApp_nonSystemUser()4781     public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4782         ApplicationInfo info = new ApplicationInfo();
4783         info.uid = Binder.getCallingUid();
4784         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4785         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4786 
4787         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4788 
4789         assertEquals(info.uid, actualUid);
4790     }
4791 
4792     @Test
testResolveNotificationUid_sameApp()4793     public void testResolveNotificationUid_sameApp() throws Exception {
4794         ApplicationInfo info = new ApplicationInfo();
4795         info.uid = Binder.getCallingUid();
4796         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
4797 
4798         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4799 
4800         assertEquals(info.uid, actualUid);
4801     }
4802 
4803     @Test
testResolveNotificationUid_sameAppDiffPackage()4804     public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
4805         ApplicationInfo info = new ApplicationInfo();
4806         info.uid = Binder.getCallingUid();
4807         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
4808 
4809         int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4810 
4811         assertEquals(info.uid, actualUid);
4812     }
4813 
4814     @Test
testResolveNotificationUid_sameAppWrongUid()4815     public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4816         ApplicationInfo info = new ApplicationInfo();
4817         info.uid = 1356347;
4818         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4819 
4820         try {
4821             mService.resolveNotificationUid("caller", "caller", 9, 0);
4822             fail("Incorrect uid didn't throw security exception");
4823         } catch (SecurityException e) {
4824             // yay
4825         }
4826     }
4827 
4828     @Test
testResolveNotificationUid_delegateAllowed()4829     public void testResolveNotificationUid_delegateAllowed() throws Exception {
4830         int expectedUid = 123;
4831 
4832         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4833         mService.setPreferencesHelper(mPreferencesHelper);
4834         when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4835                 .thenReturn(true);
4836 
4837         assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4838     }
4839 
4840     @Test
testResolveNotificationUid_androidAllowed()4841     public void testResolveNotificationUid_androidAllowed() throws Exception {
4842         int expectedUid = 123;
4843 
4844         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4845         // no delegate
4846 
4847         assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4848     }
4849 
4850     @Test
testPostFromAndroidForNonExistentPackage()4851     public void testPostFromAndroidForNonExistentPackage() throws Exception {
4852         final String notReal = "NOT REAL";
4853         when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4854                 PackageManager.NameNotFoundException.class);
4855         ApplicationInfo ai = new ApplicationInfo();
4856         ai.uid = -1;
4857         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4858 
4859         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
4860         try {
4861             mInternalService.enqueueNotification(notReal, "android", 0, 0,
4862                     "testPostFromAndroidForNonExistentPackage",
4863                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
4864             fail("can't post notifications for nonexistent packages, even if you exist");
4865         } catch (SecurityException e) {
4866             // yay
4867         }
4868     }
4869 
4870     @Test
testCancelFromAndroidForNonExistentPackage()4871     public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4872         final String notReal = "NOT REAL";
4873         when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4874                 PackageManager.NameNotFoundException.class);
4875         ApplicationInfo ai = new ApplicationInfo();
4876         ai.uid = -1;
4877         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4878 
4879         // unlike the post case, ignore instead of throwing
4880         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
4881 
4882         mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4883                 sbn.getId(), sbn.getUserId());
4884     }
4885 
4886     @Test
testResolveNotificationUid_delegateNotAllowed()4887     public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4888         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4889         // no delegate
4890 
4891         try {
4892             mService.resolveNotificationUid("caller", "target", 9, 0);
4893             fail("Incorrect uid didn't throw security exception");
4894         } catch (SecurityException e) {
4895             // yay
4896         }
4897     }
4898 
4899     @Test
testRemoveForegroundServiceFlagFromNotification_enqueued()4900     public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4901         Notification n = new Notification.Builder(mContext, "").build();
4902         n.flags |= FLAG_FOREGROUND_SERVICE;
4903 
4904         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4905                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
4906         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4907 
4908         mService.addEnqueuedNotification(r);
4909 
4910         mInternalService.removeForegroundServiceFlagFromNotification(
4911                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
4912 
4913         waitForIdle();
4914 
4915         verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4916     }
4917 
4918     @Test
testRemoveForegroundServiceFlagFromNotification_posted()4919     public void testRemoveForegroundServiceFlagFromNotification_posted() {
4920         Notification n = new Notification.Builder(mContext, "").build();
4921         n.flags |= FLAG_FOREGROUND_SERVICE;
4922 
4923         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4924                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
4925         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4926 
4927         mService.addNotification(r);
4928 
4929         mInternalService.removeForegroundServiceFlagFromNotification(
4930                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
4931 
4932         waitForIdle();
4933 
4934         ArgumentCaptor<NotificationRecord> captor =
4935                 ArgumentCaptor.forClass(NotificationRecord.class);
4936         verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4937 
4938         assertEquals(0, captor.getValue().getNotification().flags);
4939     }
4940 
4941     @Test
testAllowForegroundCustomToasts()4942     public void testAllowForegroundCustomToasts() throws Exception {
4943         final String testPackage = "testPackageName";
4944         assertEquals(0, mService.mToastQueue.size());
4945         mService.isSystemUid = false;
4946 
4947         // package is not suspended
4948         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4949                 .thenReturn(false);
4950 
4951         // notifications from this package are blocked by the user
4952         mService.setPreferencesHelper(mPreferencesHelper);
4953         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4954 
4955         setAppInForegroundForToasts(mUid, true);
4956 
4957         // enqueue toast -> toast should still enqueue
4958         ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
4959                 new TestableToastCallback(), 2000, 0);
4960         assertEquals(1, mService.mToastQueue.size());
4961     }
4962 
4963     @Test
testDisallowBackgroundCustomToasts()4964     public void testDisallowBackgroundCustomToasts() throws Exception {
4965         final String testPackage = "testPackageName";
4966         assertEquals(0, mService.mToastQueue.size());
4967         mService.isSystemUid = false;
4968 
4969         // package is not suspended
4970         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4971                 .thenReturn(false);
4972 
4973         setAppInForegroundForToasts(mUid, false);
4974 
4975         // enqueue toast -> no toasts enqueued
4976         ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
4977                 new TestableToastCallback(), 2000, 0);
4978         assertEquals(0, mService.mToastQueue.size());
4979     }
4980 
4981     @Test
testAllowForegroundTextToasts()4982     public void testAllowForegroundTextToasts() throws Exception {
4983         final String testPackage = "testPackageName";
4984         assertEquals(0, mService.mToastQueue.size());
4985         mService.isSystemUid = false;
4986 
4987         // package is not suspended
4988         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4989                 .thenReturn(false);
4990 
4991         setAppInForegroundForToasts(mUid, true);
4992 
4993         // enqueue toast -> toast should still enqueue
4994         ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4995                 "Text", 2000, 0, null);
4996         assertEquals(1, mService.mToastQueue.size());
4997     }
4998 
4999     @Test
testAllowBackgroundTextToasts()5000     public void testAllowBackgroundTextToasts() throws Exception {
5001         final String testPackage = "testPackageName";
5002         assertEquals(0, mService.mToastQueue.size());
5003         mService.isSystemUid = false;
5004 
5005         // package is not suspended
5006         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5007                 .thenReturn(false);
5008 
5009         setAppInForegroundForToasts(mUid, false);
5010 
5011         // enqueue toast -> toast should still enqueue
5012         ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
5013                 "Text", 2000, 0, null);
5014         assertEquals(1, mService.mToastQueue.size());
5015     }
5016 
5017     @Test
testTextToastsCallStatusBar()5018     public void testTextToastsCallStatusBar() throws Exception {
5019         final String testPackage = "testPackageName";
5020         assertEquals(0, mService.mToastQueue.size());
5021         mService.isSystemUid = false;
5022 
5023         // package is not suspended
5024         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5025                 .thenReturn(false);
5026 
5027         // enqueue toast -> no toasts enqueued
5028         ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
5029                 "Text", 2000, 0, null);
5030         verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
5031     }
5032 
5033     @Test
testDisallowToastsFromSuspendedPackages()5034     public void testDisallowToastsFromSuspendedPackages() throws Exception {
5035         final String testPackage = "testPackageName";
5036         assertEquals(0, mService.mToastQueue.size());
5037         mService.isSystemUid = false;
5038 
5039         // package is suspended
5040         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5041                 .thenReturn(true);
5042 
5043         // notifications from this package are NOT blocked by the user
5044         mService.setPreferencesHelper(mPreferencesHelper);
5045         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
5046 
5047         // enqueue toast -> no toasts enqueued
5048         ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
5049                 new TestableToastCallback(), 2000, 0);
5050         assertEquals(0, mService.mToastQueue.size());
5051     }
5052 
5053     @Test
testDisallowToastsFromBlockedApps()5054     public void testDisallowToastsFromBlockedApps() throws Exception {
5055         final String testPackage = "testPackageName";
5056         assertEquals(0, mService.mToastQueue.size());
5057         mService.isSystemUid = false;
5058 
5059         // package is not suspended
5060         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5061                 .thenReturn(false);
5062 
5063         // notifications from this package are blocked by the user
5064         mService.setPreferencesHelper(mPreferencesHelper);
5065         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
5066 
5067         setAppInForegroundForToasts(mUid, false);
5068 
5069         // enqueue toast -> no toasts enqueued
5070         ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
5071                 new TestableToastCallback(), 2000, 0);
5072         assertEquals(0, mService.mToastQueue.size());
5073     }
5074 
5075     @Test
testAlwaysAllowSystemToasts()5076     public void testAlwaysAllowSystemToasts() throws Exception {
5077         final String testPackage = "testPackageName";
5078         assertEquals(0, mService.mToastQueue.size());
5079         mService.isSystemUid = true;
5080 
5081         // package is suspended
5082         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5083                 .thenReturn(true);
5084 
5085         // notifications from this package ARE blocked by the user
5086         mService.setPreferencesHelper(mPreferencesHelper);
5087         when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
5088 
5089         setAppInForegroundForToasts(mUid, false);
5090 
5091         // enqueue toast -> system toast can still be enqueued
5092         ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
5093                 new TestableToastCallback(), 2000, 0);
5094         assertEquals(1, mService.mToastQueue.size());
5095     }
5096 
setAppInForegroundForToasts(int uid, boolean inForeground)5097     private void setAppInForegroundForToasts(int uid, boolean inForeground) {
5098         int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
5099         when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
5100         when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
5101     }
5102 
5103     @Test
testOnPanelRevealedAndHidden()5104     public void testOnPanelRevealedAndHidden() {
5105         int items = 5;
5106         mService.mNotificationDelegate.onPanelRevealed(false, items);
5107         verify(mAssistants, times(1)).onPanelRevealed(eq(items));
5108 
5109         mService.mNotificationDelegate.onPanelHidden();
5110         verify(mAssistants, times(1)).onPanelHidden();
5111 
5112         assertEquals(2, mNotificationRecordLogger.numCalls());
5113         assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
5114                 mNotificationRecordLogger.event(0));
5115         assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
5116                 mNotificationRecordLogger.event(1));
5117     }
5118 
5119     @Test
testOnNotificationSmartReplySent()5120     public void testOnNotificationSmartReplySent() {
5121         final int replyIndex = 2;
5122         final String reply = "Hello";
5123         final boolean modifiedBeforeSending = true;
5124         final boolean generatedByAssistant = true;
5125 
5126         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5127         r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
5128         mService.addNotification(r);
5129 
5130         mService.mNotificationDelegate.onNotificationSmartReplySent(
5131                 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
5132                 modifiedBeforeSending);
5133         verify(mAssistants).notifyAssistantSuggestedReplySent(
5134                 eq(r.getSbn()), eq(reply), eq(generatedByAssistant));
5135         assertEquals(1, mNotificationRecordLogger.numCalls());
5136         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
5137                 mNotificationRecordLogger.event(0));
5138     }
5139 
5140     @Test
testOnNotificationActionClick()5141     public void testOnNotificationActionClick() {
5142         final int actionIndex = 2;
5143         final Notification.Action action =
5144                 new Notification.Action.Builder(null, "text", null).build();
5145         final boolean generatedByAssistant = false;
5146 
5147         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5148         mService.addNotification(r);
5149 
5150         NotificationVisibility notificationVisibility =
5151                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
5152         mService.mNotificationDelegate.onNotificationActionClick(
5153                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
5154                 generatedByAssistant);
5155         verify(mAssistants).notifyAssistantActionClicked(
5156                 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
5157 
5158         assertEquals(1, mNotificationRecordLogger.numCalls());
5159         assertEquals(
5160                 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2,
5161                 mNotificationRecordLogger.event(0));
5162     }
5163 
5164     @Test
testOnAssistantNotificationActionClick()5165     public void testOnAssistantNotificationActionClick() {
5166         final int actionIndex = 1;
5167         final Notification.Action action =
5168                 new Notification.Action.Builder(null, "text", null).build();
5169         final boolean generatedByAssistant = true;
5170 
5171         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5172         mService.addNotification(r);
5173 
5174         NotificationVisibility notificationVisibility =
5175                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
5176         mService.mNotificationDelegate.onNotificationActionClick(
5177                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
5178                 generatedByAssistant);
5179         verify(mAssistants).notifyAssistantActionClicked(
5180                 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
5181 
5182         assertEquals(1, mNotificationRecordLogger.numCalls());
5183         assertEquals(
5184                 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1,
5185                 mNotificationRecordLogger.event(0));
5186     }
5187 
5188     @Test
testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()5189     public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
5190         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5191         mService.addNotification(r);
5192 
5193         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5194                 NOTIFICATION_LOCATION_UNKNOWN);
5195         NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
5196                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
5197         };
5198         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
5199                 new NotificationVisibility[0]);
5200 
5201         assertEquals(1, mService.countLogSmartSuggestionsVisible);
5202     }
5203 
5204     @Test
testLogSmartSuggestionsVisible_noTriggerOnExpand()5205     public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
5206         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5207         mService.addNotification(r);
5208 
5209         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5210                 NOTIFICATION_LOCATION_UNKNOWN);
5211 
5212         assertEquals(0, mService.countLogSmartSuggestionsVisible);
5213     }
5214 
5215     @Test
testLogSmartSuggestionsVisible_noTriggerOnVisible()5216     public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
5217         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5218         mService.addNotification(r);
5219 
5220         NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
5221                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
5222         };
5223         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
5224                 new NotificationVisibility[0]);
5225 
5226         assertEquals(0, mService.countLogSmartSuggestionsVisible);
5227     }
5228 
5229     @Test
testReportSeen_delegated()5230     public void testReportSeen_delegated() {
5231         Notification.Builder nb =
5232                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
5233                         .setContentTitle("foo")
5234                         .setSmallIcon(android.R.drawable.sym_def_app_icon);
5235 
5236         StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
5237                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
5238         NotificationRecord r =  new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5239 
5240         mService.reportSeen(r);
5241         verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
5242 
5243     }
5244 
5245     @Test
testReportSeen_notDelegated()5246     public void testReportSeen_notDelegated() {
5247         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5248 
5249         mService.reportSeen(r);
5250         verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
5251     }
5252 
5253     @Test
testNotificationStats_notificationError()5254     public void testNotificationStats_notificationError() {
5255         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5256         mService.addNotification(r);
5257 
5258         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
5259                 r.getSbn().getTag(), mUid, 0,
5260                 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
5261                 UserHandle.getUserHandleForUid(mUid), null, 0);
5262         NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5263         mService.addEnqueuedNotification(update);
5264         assertNull(update.getSbn().getNotification().getSmallIcon());
5265 
5266         NotificationManagerService.PostNotificationRunnable runnable =
5267                 mService.new PostNotificationRunnable(update.getKey());
5268         runnable.run();
5269         waitForIdle();
5270 
5271         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
5272         verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
5273         assertNotNull(captor.getValue());
5274     }
5275 
5276     @Test
testCanNotifyAsUser_crossUser()5277     public void testCanNotifyAsUser_crossUser() throws Exception {
5278         // same user no problem
5279         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
5280 
5281         // cross user, no permission, problem
5282         try {
5283             mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5284             fail("Should not be callable cross user without cross user permission");
5285         } catch (SecurityException e) {
5286             // good
5287         }
5288 
5289         // cross user, with permission, no problem
5290         enableInteractAcrossUsers();
5291         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5292     }
5293 
5294     @Test
testGetNotificationChannels_crossUser()5295     public void testGetNotificationChannels_crossUser() throws Exception {
5296         // same user no problem
5297         mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
5298 
5299         // cross user, no permission, problem
5300         try {
5301             mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5302             fail("Should not be callable cross user without cross user permission");
5303         } catch (SecurityException e) {
5304             // good
5305         }
5306 
5307         // cross user, with permission, no problem
5308         enableInteractAcrossUsers();
5309         mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5310     }
5311 
5312     @Test
setDefaultAssistantForUser_fromConfigXml()5313     public void setDefaultAssistantForUser_fromConfigXml() {
5314         clearDeviceConfig();
5315         ComponentName xmlConfig = new ComponentName("config", "xml");
5316         ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
5317         when(mResources
5318                 .getString(
5319                         com.android.internal.R.string.config_defaultAssistantAccessComponent))
5320                 .thenReturn(xmlConfig.flattenToString());
5321         when(mContext.getResources()).thenReturn(mResources);
5322         when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
5323                 .thenReturn(components);
5324         when(mAssistants.getDefaultComponents())
5325                 .thenReturn(components);
5326         mService.setNotificationAssistantAccessGrantedCallback(
5327                 mNotificationAssistantAccessGrantedCallback);
5328 
5329 
5330         mService.setDefaultAssistantForUser(0);
5331 
5332         verify(mNotificationAssistantAccessGrantedCallback)
5333                 .onGranted(eq(xmlConfig), eq(0), eq(true));
5334     }
5335 
5336     @Test
setDefaultAssistantForUser_fromDeviceConfig()5337     public void setDefaultAssistantForUser_fromDeviceConfig() {
5338         ComponentName xmlConfig = new ComponentName("xml", "config");
5339         ComponentName deviceConfig = new ComponentName("device", "config");
5340         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5341         when(mResources
5342                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5343                 .thenReturn(xmlConfig.flattenToString());
5344         when(mContext.getResources()).thenReturn(mResources);
5345         when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
5346                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
5347         when(mAssistants.getDefaultComponents())
5348                 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
5349         mService.setNotificationAssistantAccessGrantedCallback(
5350                 mNotificationAssistantAccessGrantedCallback);
5351 
5352         mService.setDefaultAssistantForUser(0);
5353 
5354         verify(mNotificationAssistantAccessGrantedCallback)
5355                 .onGranted(eq(deviceConfig), eq(0), eq(true));
5356     }
5357 
5358     @Test
setDefaultAssistantForUser_deviceConfigInvalid()5359     public void setDefaultAssistantForUser_deviceConfigInvalid() {
5360         ComponentName xmlConfig = new ComponentName("xml", "config");
5361         ComponentName deviceConfig = new ComponentName("device", "config");
5362         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5363         when(mResources
5364                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5365                 .thenReturn(xmlConfig.flattenToString());
5366         when(mContext.getResources()).thenReturn(mResources);
5367         // Only xmlConfig is valid, deviceConfig is not.
5368         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
5369                 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
5370         when(mAssistants.getDefaultComponents())
5371                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
5372         mService.setNotificationAssistantAccessGrantedCallback(
5373                 mNotificationAssistantAccessGrantedCallback);
5374 
5375         mService.setDefaultAssistantForUser(0);
5376 
5377         verify(mNotificationAssistantAccessGrantedCallback)
5378                 .onGranted(eq(xmlConfig), eq(0), eq(true));
5379     }
5380 
5381     @Test
clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne()5382     public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
5383         ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
5384                 generateResetComponentValues();
5385         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
5386         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5387         ComponentName deviceConfig1 = new ComponentName("device", "config1");
5388         ComponentName deviceConfig2 = new ComponentName("device", "config2");
5389         changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
5390         changes.put(false, new ArrayList());
5391         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
5392         mService.getBinderService().clearData("device", 0, false);
5393         verify(mAssistants, times(1))
5394                 .setPackageOrComponentEnabled(
5395                         eq("device/config2"),
5396                         eq(0), eq(true), eq(false));
5397         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5398                 eq("device"), eq(0), eq(false), eq(true));
5399     }
5400 
5401     @Test
clearDefaultListenersPackageShouldEnableIt()5402     public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
5403         ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
5404                 generateResetComponentValues();
5405         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
5406         ComponentName deviceConfig = new ComponentName("device", "config");
5407         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5408         changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
5409         changes.put(false, new ArrayList());
5410         when(mListeners.resetComponents(anyString(), anyInt()))
5411             .thenReturn(changes);
5412         mService.getBinderService().clearData("device", 0, false);
5413         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5414                 eq("device"), eq(0), eq(false), eq(true));
5415     }
5416 
5417     @Test
clearDefaultDnDPackageShouldEnableIt()5418     public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
5419         ComponentName deviceConfig = new ComponentName("device", "config");
5420         ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
5421         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
5422         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
5423         mService.getBinderService().clearData("device", 0, false);
5424         verify(mConditionProviders, times(1)).resetPackage(
5425                         eq("device"), eq(0));
5426     }
5427 
5428     @Test
testFlagBubble()5429     public void testFlagBubble() throws RemoteException {
5430         setUpPrefsForBubbles(PKG, mUid,
5431                 true /* global */,
5432                 BUBBLE_PREFERENCE_ALL /* app */,
5433                 true /* channel */);
5434 
5435         NotificationRecord nr =
5436                 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
5437 
5438         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5439                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5440         waitForIdle();
5441 
5442         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5443         assertEquals(1, notifs.length);
5444         assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
5445         assertTrue(mService.getNotificationRecord(
5446                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5447     }
5448 
5449     @Test
testFlagBubble_noFlag_appNotAllowed()5450     public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
5451         setUpPrefsForBubbles(PKG, mUid,
5452                 true /* global */,
5453                 BUBBLE_PREFERENCE_NONE /* app */,
5454                 true /* channel */);
5455 
5456         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5457                         "testFlagBubble_noFlag_appNotAllowed");
5458 
5459         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5460                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5461         waitForIdle();
5462 
5463         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5464         assertEquals(1, notifs.length);
5465         assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
5466         assertFalse(mService.getNotificationRecord(
5467                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5468     }
5469 
5470     @Test
testFlagBubbleNotifs_noFlag_whenAppForeground()5471     public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
5472         setUpPrefsForBubbles(PKG, mUid,
5473                 true /* global */,
5474                 BUBBLE_PREFERENCE_ALL /* app */,
5475                 true /* channel */);
5476 
5477         // Notif with bubble metadata but not our other misc requirements
5478         Notification.Builder nb = new Notification.Builder(mContext,
5479                 mTestNotificationChannel.getId())
5480                 .setContentTitle("foo")
5481                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5482                 .setBubbleMetadata(getBubbleMetadata());
5483         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
5484                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
5485         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5486 
5487         // Say we're foreground
5488         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
5489                 IMPORTANCE_FOREGROUND);
5490         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5491                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5492         waitForIdle();
5493 
5494         // if notif isn't configured properly it doesn't get to bubble just because app is
5495         // foreground.
5496         assertFalse(mService.getNotificationRecord(
5497                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5498     }
5499 
5500     @Test
testFlagBubbleNotifs_flag_messaging()5501     public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
5502         setUpPrefsForBubbles(PKG, mUid,
5503                 true /* global */,
5504                 BUBBLE_PREFERENCE_ALL /* app */,
5505                 true /* channel */);
5506 
5507         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5508                 "testFlagBubbleNotifs_flag_messaging");
5509 
5510         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5511                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5512         waitForIdle();
5513 
5514         // yes allowed, yes messaging, yes bubble
5515         assertTrue(mService.getNotificationRecord(
5516                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5517     }
5518 
5519     @Test
testFlagBubbleNotifs_noFlag_noShortcut()5520     public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException {
5521         setUpPrefsForBubbles(PKG, mUid,
5522                 true /* global */,
5523                 BUBBLE_PREFERENCE_ALL /* app */,
5524                 true /* channel */);
5525 
5526         Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false);
5527         nb.setShortcutId(null);
5528         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5529                 null, mUid, 0,
5530                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
5531 
5532         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
5533                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
5534         waitForIdle();
5535 
5536         // no shortcut no bubble
5537         assertFalse(mService.getNotificationRecord(
5538                 sbn.getKey()).getNotification().isBubbleNotification());
5539     }
5540 
5541     @Test
testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()5542     public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
5543         setUpPrefsForBubbles(PKG, mUid,
5544                 true /* global */,
5545                 BUBBLE_PREFERENCE_NONE /* app */,
5546                 true /* channel */);
5547 
5548         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5549                 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
5550 
5551         // Post the notification
5552         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5553                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5554         waitForIdle();
5555 
5556         // not allowed, no bubble
5557         assertFalse(mService.getNotificationRecord(
5558                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5559     }
5560 
5561     @Test
testFlagBubbleNotifs_noFlag_notBubble()5562     public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
5563         setUpPrefsForBubbles(PKG, mUid,
5564                 true /* global */,
5565                 BUBBLE_PREFERENCE_ALL /* app */,
5566                 true /* channel */);
5567 
5568         // Messaging notif WITHOUT bubble metadata
5569         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
5570                 null /* groupKey */, false /* isSummary */);
5571 
5572         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5573                 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
5574                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
5575         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5576 
5577         // Post the notification
5578         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5579                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5580         waitForIdle();
5581 
5582         // no bubble metadata, no bubble
5583         assertFalse(mService.getNotificationRecord(
5584                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5585     }
5586 
5587     @Test
testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()5588     public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
5589         setUpPrefsForBubbles(PKG, mUid,
5590                 true /* global */,
5591                 BUBBLE_PREFERENCE_ALL /* app */,
5592                 false /* channel */);
5593 
5594         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5595                 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
5596         nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
5597 
5598         // Post the notification
5599         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5600                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5601         waitForIdle();
5602 
5603         // channel not allowed, no bubble
5604         assertFalse(mService.getNotificationRecord(
5605                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
5606     }
5607 
5608     @Test
testCancelNotificationsFromApp_cancelsBubbles()5609     public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
5610         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5611         nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
5612 
5613         // Post the notification
5614         mBinderService.enqueueNotificationWithTag(PKG, PKG,
5615                 "testAppCancelNotifications_cancelsBubbles",
5616                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
5617                 nrBubble.getSbn().getUserId());
5618         waitForIdle();
5619 
5620         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5621         assertEquals(1, notifs.length);
5622         assertEquals(1, mService.getNotificationRecordCount());
5623 
5624         mBinderService.cancelNotificationWithTag(PKG, PKG,
5625                 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
5626                 nrBubble.getSbn().getUserId());
5627         waitForIdle();
5628 
5629         StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5630         assertEquals(0, notifs2.length);
5631         assertEquals(0, mService.getNotificationRecordCount());
5632     }
5633 
5634     @Test
testCancelAllNotificationsFromApp_cancelsBubble()5635     public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
5636         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5637         nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5638         mService.addNotification(nr);
5639 
5640         mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
5641         waitForIdle();
5642 
5643         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5644         assertEquals(0, notifs.length);
5645         assertEquals(0, mService.getNotificationRecordCount());
5646     }
5647 
5648     @Test
testCancelAllNotificationsFromListener_ignoresBubbles()5649     public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5650         final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5651         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5652         nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
5653 
5654         mService.addNotification(nrNormal);
5655         mService.addNotification(nrBubble);
5656 
5657         mService.getBinderService().cancelNotificationsFromListener(null, null);
5658         waitForIdle();
5659 
5660         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5661         assertEquals(1, notifs.length);
5662         assertEquals(1, mService.getNotificationRecordCount());
5663     }
5664 
5665     @Test
testCancelNotificationsFromListener_cancelsNonBubble()5666     public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception {
5667         // Add non-bubble notif
5668         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5669         mService.addNotification(nr);
5670 
5671         // Cancel via listener
5672         String[] keys = {nr.getSbn().getKey()};
5673         mService.getBinderService().cancelNotificationsFromListener(null, keys);
5674         waitForIdle();
5675 
5676         // Notif not active anymore
5677         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5678         assertEquals(0, notifs.length);
5679         assertEquals(0, mService.getNotificationRecordCount());
5680         // Cancel event is logged
5681         assertEquals(1, mNotificationRecordLogger.numCalls());
5682         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
5683             .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
5684     }
5685 
5686     @Test
testCancelNotificationsFromListener_suppressesBubble()5687     public void testCancelNotificationsFromListener_suppressesBubble() throws Exception {
5688         // Add bubble notif
5689         setUpPrefsForBubbles(PKG, mUid,
5690             true /* global */,
5691             BUBBLE_PREFERENCE_ALL /* app */,
5692             true /* channel */);
5693         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5694 
5695         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5696             nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5697         waitForIdle();
5698 
5699         // Cancel via listener
5700         String[] keys = {nr.getSbn().getKey()};
5701         mService.getBinderService().cancelNotificationsFromListener(null, keys);
5702         waitForIdle();
5703 
5704         // Bubble notif active and suppressed
5705         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5706         assertEquals(1, notifs.length);
5707         assertEquals(1, mService.getNotificationRecordCount());
5708         assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed());
5709     }
5710 
5711     @Test
testCancelAllNotificationsFromStatusBar_ignoresBubble()5712     public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
5713         // GIVEN a notification bubble
5714         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5715         nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5716         mService.addNotification(nr);
5717 
5718         // WHEN the status bar clears all notifications
5719         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
5720                 nr.getSbn().getUserId());
5721         waitForIdle();
5722 
5723         // THEN the bubble notification does not get removed
5724         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5725         assertEquals(1, notifs.length);
5726         assertEquals(1, mService.getNotificationRecordCount());
5727     }
5728 
5729 
5730     @Test
testGetAllowedAssistantAdjustments()5731     public void testGetAllowedAssistantAdjustments() throws Exception {
5732         List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
5733         assertNotNull(capabilities);
5734 
5735         for (int i = capabilities.size() - 1; i >= 0; i--) {
5736             String capability = capabilities.get(i);
5737             mBinderService.disallowAssistantAdjustment(capability);
5738             assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5739             List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
5740             assertNotNull(currentCapabilities);
5741             assertFalse(currentCapabilities.contains(capability));
5742         }
5743     }
5744 
5745     @Test
testAdjustRestrictedKey()5746     public void testAdjustRestrictedKey() throws Exception {
5747         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5748         mService.addNotification(r);
5749         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
5750 
5751         when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5752         when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5753 
5754         Bundle signals = new Bundle();
5755         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5756         signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
5757         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
5758                "", r.getUser().getIdentifier());
5759 
5760         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5761         r.applyAdjustments();
5762 
5763         assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5764         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5765     }
5766 
5767     @Test
testAutomaticZenRuleValidation_policyFilterAgreement()5768     public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
5769         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5770                 .thenReturn(true);
5771         mService.setZenHelper(mock(ZenModeHelper.class));
5772         ComponentName owner = new ComponentName(mContext, this.getClass());
5773         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5774         boolean isEnabled = true;
5775         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5776                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5777 
5778         try {
5779             mBinderService.addAutomaticZenRule(rule);
5780             fail("Zen policy only applies to priority only mode");
5781         } catch (IllegalArgumentException e) {
5782             // yay
5783         }
5784 
5785         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5786                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5787         mBinderService.addAutomaticZenRule(rule);
5788 
5789         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5790                 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5791         mBinderService.addAutomaticZenRule(rule);
5792     }
5793 
5794     @Test
testAreNotificationsEnabledForPackage_crossUser()5795     public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5796         try {
5797             mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5798                     mUid + UserHandle.PER_USER_RANGE);
5799             fail("Cannot call cross user without permission");
5800         } catch (SecurityException e) {
5801             // pass
5802         }
5803 
5804         // cross user, with permission, no problem
5805         enableInteractAcrossUsers();
5806         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5807                 mUid + UserHandle.PER_USER_RANGE);
5808     }
5809 
5810     @Test
testAreBubblesAllowedForPackage_crossUser()5811     public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5812         try {
5813             mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
5814                     mUid + UserHandle.PER_USER_RANGE);
5815             fail("Cannot call cross user without permission");
5816         } catch (SecurityException e) {
5817             // pass
5818         }
5819 
5820         // cross user, with permission, no problem
5821         enableInteractAcrossUsers();
5822         mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
5823                 mUid + UserHandle.PER_USER_RANGE);
5824     }
5825 
enableInteractAcrossUsers()5826     private void enableInteractAcrossUsers() {
5827         TestablePermissions perms = mContext.getTestablePermissions();
5828         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5829     }
5830 
5831     @Test
testNotificationBubbleChanged_false()5832     public void testNotificationBubbleChanged_false() throws Exception {
5833         setUpPrefsForBubbles(PKG, mUid,
5834                 true /* global */,
5835                 BUBBLE_PREFERENCE_ALL /* app */,
5836                 true /* channel */);
5837 
5838         // Notif with bubble metadata
5839         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5840                 "testNotificationBubbleChanged_false");
5841 
5842         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5843                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5844         waitForIdle();
5845 
5846         // Reset as this is called when the notif is first sent
5847         reset(mListeners);
5848 
5849         // First we were a bubble
5850         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5851         assertEquals(1, notifsBefore.length);
5852         assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5853 
5854         // Notify we're not a bubble
5855         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
5856         waitForIdle();
5857 
5858         // Make sure we are not a bubble
5859         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5860         assertEquals(1, notifsAfter.length);
5861         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5862     }
5863 
5864     @Test
testNotificationBubbleChanged_true()5865     public void testNotificationBubbleChanged_true() throws Exception {
5866         setUpPrefsForBubbles(PKG, mUid,
5867                 true /* global */,
5868                 BUBBLE_PREFERENCE_ALL /* app */,
5869                 true /* channel */);
5870 
5871         // Notif that is not a bubble
5872         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5873                 1, null, false);
5874         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5875                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5876         waitForIdle();
5877 
5878         // Would be a normal notification because wouldn't have met requirements to bubble
5879         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5880         assertEquals(1, notifsBefore.length);
5881         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5882 
5883         // Update the notification to be message style / meet bubble requirements
5884         NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5885                 nr.getSbn().getTag());
5886         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
5887                 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
5888         waitForIdle();
5889 
5890         // Reset as this is called when the notif is first sent
5891         reset(mListeners);
5892 
5893         // Notify we are now a bubble
5894         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
5895         waitForIdle();
5896 
5897         // Make sure we are a bubble
5898         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5899         assertEquals(1, notifsAfter.length);
5900         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
5901     }
5902 
5903     @Test
testNotificationBubbleChanged_true_notAllowed()5904     public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5905         setUpPrefsForBubbles(PKG, mUid,
5906                 true /* global */,
5907                 BUBBLE_PREFERENCE_ALL /* app */,
5908                 true /* channel */);
5909 
5910         // Notif that is not a bubble
5911         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5912         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5913                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5914         waitForIdle();
5915 
5916         // Reset as this is called when the notif is first sent
5917         reset(mListeners);
5918 
5919         // Would be a normal notification because wouldn't have met requirements to bubble
5920         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5921         assertEquals(1, notifsBefore.length);
5922         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5923 
5924         // Notify we are now a bubble
5925         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
5926         waitForIdle();
5927 
5928         // We still wouldn't be a bubble because the notification didn't meet requirements
5929         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5930         assertEquals(1, notifsAfter.length);
5931         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5932     }
5933 
5934     @Test
testNotificationBubbleIsFlagRemoved_resetOnUpdate()5935     public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
5936         setUpPrefsForBubbles(PKG, mUid,
5937                 true /* global */,
5938                 BUBBLE_PREFERENCE_ALL /* app */,
5939                 true /* channel */);
5940 
5941         // Notif with bubble metadata
5942         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5943                 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
5944 
5945         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5946                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5947         waitForIdle();
5948         // Flag shouldn't be modified
5949         NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5950         assertFalse(recordToCheck.isFlagBubbleRemoved());
5951 
5952         // Notify we're not a bubble
5953         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
5954         waitForIdle();
5955         // Flag should be modified
5956         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5957         assertTrue(recordToCheck.isFlagBubbleRemoved());
5958 
5959 
5960         // Update the notif
5961         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5962                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5963         waitForIdle();
5964         // And the flag is reset
5965         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5966         assertFalse(recordToCheck.isFlagBubbleRemoved());
5967     }
5968 
5969     @Test
testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue()5970     public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
5971         setUpPrefsForBubbles(PKG, mUid,
5972                 true /* global */,
5973                 BUBBLE_PREFERENCE_ALL /* app */,
5974                 true /* channel */);
5975 
5976         // Notif with bubble metadata
5977         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5978                 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
5979 
5980         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5981                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5982         waitForIdle();
5983         // Flag shouldn't be modified
5984         NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5985         assertFalse(recordToCheck.isFlagBubbleRemoved());
5986 
5987         // Notify we're not a bubble
5988         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
5989         waitForIdle();
5990         // Flag should be modified
5991         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5992         assertTrue(recordToCheck.isFlagBubbleRemoved());
5993 
5994         // Notify we are a bubble
5995         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
5996         waitForIdle();
5997         // And the flag is reset
5998         assertFalse(recordToCheck.isFlagBubbleRemoved());
5999     }
6000 
6001     @Test
testOnBubbleNotificationSuppressionChanged()6002     public void testOnBubbleNotificationSuppressionChanged() throws Exception {
6003         setUpPrefsForBubbles(PKG, mUid,
6004                 true /* global */,
6005                 BUBBLE_PREFERENCE_ALL /* app */,
6006                 true /* channel */);
6007 
6008         // Bubble notification
6009         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
6010 
6011         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6012                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6013         waitForIdle();
6014 
6015         // NOT suppressed
6016         Notification n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
6017         assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
6018 
6019         // Reset as this is called when the notif is first sent
6020         reset(mListeners);
6021 
6022         // Test: update suppression to true
6023         mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
6024         waitForIdle();
6025 
6026         // Check
6027         n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
6028         assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
6029 
6030         // Reset to check again
6031         reset(mListeners);
6032 
6033         // Test: update suppression to false
6034         mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
6035         waitForIdle();
6036 
6037         // Check
6038         n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
6039         assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
6040     }
6041 
6042     @Test
testGrantInlineReplyUriPermission_recordExists()6043     public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
6044         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6045         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
6046                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6047         waitForIdle();
6048 
6049         // A notification exists for the given record
6050         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6051         assertEquals(1, notifsBefore.length);
6052 
6053         reset(mPackageManager);
6054 
6055         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6056 
6057         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6058                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6059                 nr.getSbn().getUid());
6060 
6061         // Grant permission called for the UID of SystemUI under the target user ID
6062         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
6063                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
6064                 anyInt(), eq(nr.getSbn().getUserId()));
6065     }
6066 
6067     @Test
testGrantInlineReplyUriPermission_noRecordExists()6068     public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
6069         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6070         waitForIdle();
6071 
6072         // No notifications exist for the given record
6073         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6074         assertEquals(0, notifsBefore.length);
6075 
6076         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6077         int uid = 0; // sysui on primary user
6078 
6079         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6080                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6081                 nr.getSbn().getUid());
6082 
6083         // Grant permission still called if no NotificationRecord exists for the given key
6084         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
6085                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
6086                 anyInt(), eq(nr.getSbn().getUserId()));
6087     }
6088 
6089     @Test
testGrantInlineReplyUriPermission_userAll()6090     public void testGrantInlineReplyUriPermission_userAll() throws Exception {
6091         // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
6092         NotificationRecord nr =
6093                 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
6094         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
6095                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6096         waitForIdle();
6097 
6098         // A notification exists for the given record
6099         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6100         assertEquals(1, notifsBefore.length);
6101 
6102         reset(mPackageManager);
6103 
6104         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6105 
6106         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6107                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6108                 nr.getSbn().getUid());
6109 
6110         // Target user for the grant is USER_ALL instead of USER_SYSTEM
6111         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
6112                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
6113                 anyInt(), eq(UserHandle.USER_SYSTEM));
6114     }
6115 
6116     @Test
testGrantInlineReplyUriPermission_acrossUsers()6117     public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
6118         // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
6119         int otherUserId = 11;
6120         NotificationRecord nr =
6121                 generateNotificationRecord(mTestNotificationChannel, otherUserId);
6122         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
6123                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6124         waitForIdle();
6125 
6126         // A notification exists for the given record
6127         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6128         assertEquals(1, notifsBefore.length);
6129 
6130         reset(mPackageManager);
6131 
6132         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6133 
6134         int uid = 0; // sysui on primary user
6135         int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
6136         String sysuiPackage = "sysui";
6137         final String[] sysuiPackages = new String[] { sysuiPackage };
6138         when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
6139 
6140         // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
6141         // time this is called
6142         when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
6143                 .thenReturn(otherUserUid);
6144 
6145         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6146                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
6147 
6148         // Target user for the grant is USER_ALL instead of USER_SYSTEM
6149         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
6150                 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
6151                 eq(otherUserId));
6152     }
6153 
6154     @Test
testClearInlineReplyUriPermission_uriRecordExists()6155     public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
6156         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6157         reset(mPackageManager);
6158 
6159         Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6160         Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
6161 
6162         // create an inline record with two uris in it
6163         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6164                 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6165                 nr.getSbn().getUid());
6166         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6167                 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6168                 nr.getSbn().getUid());
6169 
6170         InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
6171         assertNotNull(record); // record exists
6172         assertEquals(record.getUris().size(), 2); // record has two uris in it
6173 
6174         mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
6175                 nr.getSbn().getUid());
6176 
6177         // permissionOwner destroyed
6178         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
6179                 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
6180     }
6181 
6182 
6183     @Test
testClearInlineReplyUriPermission_noUriRecordExists()6184     public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
6185         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6186         reset(mPackageManager);
6187 
6188         mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
6189                 nr.getSbn().getUid());
6190 
6191         // no permissionOwner destroyed
6192         verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
6193                 any(), eq(null), eq(~0), eq(nr.getUserId()));
6194     }
6195 
6196     @Test
testClearInlineReplyUriPermission_userAll()6197     public void testClearInlineReplyUriPermission_userAll() throws Exception {
6198         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
6199                 UserHandle.USER_ALL);
6200         reset(mPackageManager);
6201 
6202         Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6203         Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
6204 
6205         // create an inline record a uri in it
6206         mService.mNotificationDelegate.grantInlineReplyUriPermission(
6207                 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6208                 nr.getSbn().getUid());
6209 
6210         InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
6211         assertNotNull(record); // record exists
6212 
6213         mService.mNotificationDelegate.clearInlineReplyUriPermissions(
6214                 nr.getKey(), nr.getSbn().getUid());
6215 
6216         // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
6217         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
6218                 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
6219     }
6220 
6221     @Test
testNotificationBubbles_disabled_lowRamDevice()6222     public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
6223         setUpPrefsForBubbles(PKG, mUid,
6224                 true /* global */,
6225                 BUBBLE_PREFERENCE_ALL /* app */,
6226                 true /* channel */);
6227 
6228         // And we are low ram
6229         when(mActivityManager.isLowRamDevice()).thenReturn(true);
6230 
6231         // Notification that would typically bubble
6232         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6233                 "testNotificationBubbles_disabled_lowRamDevice");
6234         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6235                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6236         waitForIdle();
6237 
6238         // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
6239         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6240         assertEquals(1, notifsAfter.length);
6241         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
6242     }
6243 
6244     @Test
testRemoveLargeRemoteViews()6245     public void testRemoveLargeRemoteViews() throws Exception {
6246         int removeSize = mContext.getResources().getInteger(
6247                 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
6248 
6249         RemoteViews rv = mock(RemoteViews.class);
6250         when(rv.estimateMemoryUsage()).thenReturn(removeSize);
6251         when(rv.clone()).thenReturn(rv);
6252         RemoteViews rv1 = mock(RemoteViews.class);
6253         when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
6254         when(rv1.clone()).thenReturn(rv1);
6255         RemoteViews rv2 = mock(RemoteViews.class);
6256         when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
6257         when(rv2.clone()).thenReturn(rv2);
6258         RemoteViews rv3 = mock(RemoteViews.class);
6259         when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
6260         when(rv3.clone()).thenReturn(rv3);
6261         RemoteViews rv4 = mock(RemoteViews.class);
6262         when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
6263         when(rv4.clone()).thenReturn(rv4);
6264         // note: different!
6265         RemoteViews rv5 = mock(RemoteViews.class);
6266         when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
6267         when(rv5.clone()).thenReturn(rv5);
6268 
6269         Notification np = new Notification.Builder(mContext, "test")
6270                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6271                 .setContentText("test")
6272                 .setCustomContentView(rv)
6273                 .setCustomBigContentView(rv1)
6274                 .setCustomHeadsUpContentView(rv2)
6275                 .build();
6276         Notification n = new Notification.Builder(mContext, "test")
6277                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6278                 .setContentText("test")
6279                 .setCustomContentView(rv3)
6280                 .setCustomBigContentView(rv4)
6281                 .setCustomHeadsUpContentView(rv5)
6282                 .setPublicVersion(np)
6283                 .build();
6284 
6285         assertNotNull(np.contentView);
6286         assertNotNull(np.bigContentView);
6287         assertNotNull(np.headsUpContentView);
6288 
6289         assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
6290         assertNotNull(n.publicVersion.contentView);
6291         assertNotNull(n.publicVersion.bigContentView);
6292         assertNotNull(n.publicVersion.headsUpContentView);
6293 
6294         mService.fixNotification(n, PKG, "tag", 9, 0);
6295 
6296         assertNull(n.contentView);
6297         assertNull(n.bigContentView);
6298         assertNotNull(n.headsUpContentView);
6299         assertNull(n.publicVersion.contentView);
6300         assertNull(n.publicVersion.bigContentView);
6301         assertNull(n.publicVersion.headsUpContentView);
6302 
6303         verify(mUsageStats, times(5)).registerImageRemoved(PKG);
6304     }
6305 
6306     @Test
testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()6307     public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
6308             throws Exception {
6309         setUpPrefsForBubbles(PKG, mUid,
6310                 true /* global */,
6311                 BUBBLE_PREFERENCE_ALL /* app */,
6312                 true /* channel */);
6313 
6314         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6315                 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
6316         // Modify metadata flags
6317         nr.getSbn().getNotification().getBubbleMetadata().setFlags(
6318                 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6319                         | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
6320 
6321         // Ensure we're not foreground
6322         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
6323                 IMPORTANCE_VISIBLE);
6324 
6325         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6326                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6327         waitForIdle();
6328 
6329         // yes allowed, yes messaging, yes bubble
6330         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6331         assertTrue(notif.isBubbleNotification());
6332 
6333         // Our flags should have failed since we're not foreground
6334         assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
6335         assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
6336     }
6337 
6338     @Test
testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()6339     public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
6340             throws RemoteException {
6341         setUpPrefsForBubbles(PKG, mUid,
6342                 true /* global */,
6343                 BUBBLE_PREFERENCE_ALL /* app */,
6344                 true /* channel */);
6345 
6346         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6347                 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
6348         // Modify metadata flags
6349         nr.getSbn().getNotification().getBubbleMetadata().setFlags(
6350                 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6351                         | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
6352 
6353         // Ensure we are in the foreground
6354         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
6355                 IMPORTANCE_FOREGROUND);
6356 
6357         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6358                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6359         waitForIdle();
6360 
6361         // yes allowed, yes messaging, yes bubble
6362         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6363         assertTrue(notif.isBubbleNotification());
6364 
6365         // Our flags should have passed since we are foreground
6366         assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
6367         assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
6368     }
6369 
6370     @Test
testNotificationBubbles_flagRemoved_whenShortcutRemoved()6371     public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
6372             throws RemoteException {
6373         setUpPrefsForBubbles(PKG, mUid,
6374                 true /* global */,
6375                 BUBBLE_PREFERENCE_ALL /* app */,
6376                 true /* channel */);
6377 
6378         ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6379                 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6380 
6381         // Messaging notification with shortcut info
6382         Notification.BubbleMetadata metadata =
6383                 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build();
6384         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6385                 null /* groupKey */, false /* isSummary */);
6386         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
6387         nb.setBubbleMetadata(metadata);
6388         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6389                 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6390         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6391 
6392         // Test: Send the bubble notification
6393         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6394                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6395         waitForIdle();
6396 
6397         // Verify:
6398 
6399         // Make sure we register the callback for shortcut changes
6400         verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6401 
6402         // yes allowed, yes messaging w/shortcut, yes bubble
6403         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6404         assertTrue(notif.isBubbleNotification());
6405 
6406         // Make sure the shortcut is cached.
6407         verify(mShortcutServiceInternal).cacheShortcuts(
6408                 anyInt(), any(), eq(PKG), eq(Collections.singletonList(VALID_CONVO_SHORTCUT_ID)),
6409                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
6410 
6411         // Test: Remove the shortcut
6412         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
6413         launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
6414                 UserHandle.getUserHandleForUid(mUid));
6415         waitForIdle();
6416 
6417         // Verify:
6418 
6419         // Make sure callback is unregistered
6420         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6421 
6422         // We're no longer a bubble
6423         NotificationRecord notif2 = mService.getNotificationRecord(
6424                 nr.getSbn().getKey());
6425         assertNull(notif2.getShortcutInfo());
6426         assertFalse(notif2.getNotification().isBubbleNotification());
6427     }
6428 
6429     @Test
testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()6430     public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
6431             throws RemoteException {
6432         final String shortcutId = "someshortcutId";
6433         setUpPrefsForBubbles(PKG, mUid,
6434                 true /* global */,
6435                 BUBBLE_PREFERENCE_ALL /* app */,
6436                 true /* channel */);
6437 
6438         ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6439                 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6440 
6441         // Messaging notification with shortcut info
6442         Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
6443                 shortcutId).build();
6444         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6445                 null /* groupKey */, false /* isSummary */);
6446         nb.setShortcutId(shortcutId);
6447         nb.setBubbleMetadata(metadata);
6448         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6449                 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6450         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6451 
6452         // Pretend the shortcut exists
6453         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
6454         ShortcutInfo info = mock(ShortcutInfo.class);
6455         when(info.getPackage()).thenReturn(PKG);
6456         when(info.getId()).thenReturn(shortcutId);
6457         when(info.getUserId()).thenReturn(USER_SYSTEM);
6458         when(info.isLongLived()).thenReturn(true);
6459         when(info.isEnabled()).thenReturn(true);
6460         shortcutInfos.add(info);
6461         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
6462         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6463                 anyString(), anyInt(), any())).thenReturn(true);
6464 
6465         // Test: Send the bubble notification
6466         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6467                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6468         waitForIdle();
6469 
6470         // Verify:
6471 
6472         // Make sure we register the callback for shortcut changes
6473         verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6474 
6475         // yes allowed, yes messaging w/shortcut, yes bubble
6476         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6477         assertTrue(notif.isBubbleNotification());
6478 
6479         // Make sure the shortcut is cached.
6480         verify(mShortcutServiceInternal).cacheShortcuts(
6481                 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
6482                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
6483 
6484         // Test: Remove the notification
6485         mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6486                 nr.getSbn().getId(), nr.getSbn().getUserId());
6487         waitForIdle();
6488 
6489         // Verify:
6490 
6491         // Make sure callback is unregistered
6492         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6493     }
6494 
6495     @Test
testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()6496     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
6497             throws Exception {
6498         setUpPrefsForBubbles(PKG, mUid,
6499                 true /* global */,
6500                 BUBBLE_PREFERENCE_ALL /* app */,
6501                 true /* channel */);
6502 
6503         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6504                 true /* summaryAutoCancel */);
6505 
6506         // Dismiss summary
6507         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6508                 true);
6509         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
6510                 nrSummary.getSbn().getTag(),
6511                 nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
6512                 NotificationStats.DISMISSAL_SHADE,
6513                 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
6514         waitForIdle();
6515 
6516         // The bubble should still exist
6517         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6518         assertEquals(1, notifsAfter.length);
6519     }
6520 
6521     @Test
testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()6522     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
6523             throws Exception {
6524         setUpPrefsForBubbles(PKG, mUid,
6525                 true /* global */,
6526                 BUBBLE_PREFERENCE_ALL /* app */,
6527                 true /* channel */);
6528 
6529         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6530                 true /* summaryAutoCancel */);
6531 
6532         // Click summary
6533         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6534                 true);
6535         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6536                 nrSummary.getKey(), nv);
6537         waitForIdle();
6538 
6539         // The bubble should still exist
6540         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6541         assertEquals(1, notifsAfter.length);
6542 
6543         // Check we got the click log and associated dismissal logs
6544         assertEquals(6, mNotificationRecordLogger.numCalls());
6545         // Skip the notification-creation logs
6546         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6547                 mNotificationRecordLogger.event(3));
6548         assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
6549                 mNotificationRecordLogger.event(4));
6550         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
6551                         .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
6552                 mNotificationRecordLogger.event(5));
6553     }
6554 
6555     @Test
testNotificationBubbles_bubbleStays_whenClicked()6556     public void testNotificationBubbles_bubbleStays_whenClicked()
6557             throws Exception {
6558         setUpPrefsForBubbles(PKG, mUid,
6559                 true /* global */,
6560                 BUBBLE_PREFERENCE_ALL /* app */,
6561                 true /* channel */);
6562 
6563         // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
6564         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
6565         nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
6566         mService.addNotification(nr);
6567 
6568         // WHEN we click the notification
6569         final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
6570         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6571                 nr.getKey(), nv);
6572         waitForIdle();
6573 
6574         // THEN the bubble should still exist
6575         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6576         assertEquals(1, notifsAfter.length);
6577 
6578         // Check we got the click log
6579         assertEquals(1, mNotificationRecordLogger.numCalls());
6580         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6581                 mNotificationRecordLogger.event(0));
6582     }
6583 
6584     @Test
testLoadDefaultApprovedServices_emptyResources()6585     public void testLoadDefaultApprovedServices_emptyResources() {
6586         TestableResources tr = mContext.getOrCreateTestableResources();
6587         tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
6588         tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
6589         tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
6590         setDefaultAssistantInDeviceConfig("");
6591 
6592         mService.loadDefaultApprovedServices(USER_SYSTEM);
6593 
6594         verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
6595         verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
6596         verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
6597     }
6598 
6599     @Test
testLoadDefaultApprovedServices_dnd()6600     public void testLoadDefaultApprovedServices_dnd() {
6601         TestableResources tr = mContext.getOrCreateTestableResources();
6602         tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
6603         when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
6604                 .thenReturn(new ArraySet<>());
6605 
6606         mService.loadDefaultApprovedServices(USER_SYSTEM);
6607 
6608         verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
6609     }
6610 
6611     // TODO: add tests for the rest of the non-empty cases
6612 
6613     @Test
testOnUnlockUser()6614     public void testOnUnlockUser() {
6615         UserInfo ui = new UserInfo();
6616         ui.id = 10;
6617         mService.onUnlockUser(ui);
6618         waitForIdle();
6619 
6620         verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
6621     }
6622 
6623     @Test
testOnStopUser()6624     public void testOnStopUser() {
6625         UserInfo ui = new UserInfo();
6626         ui.id = 10;
6627         mService.onStopUser(ui);
6628         waitForIdle();
6629 
6630         verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
6631     }
6632 
6633     @Test
testOnBootPhase()6634     public void testOnBootPhase() {
6635         mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
6636 
6637         verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
6638 
6639         mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
6640 
6641         verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart();
6642     }
6643 
6644     @Test
testHandleOnPackageChanged()6645     public void testHandleOnPackageChanged() {
6646         String[] pkgs = new String[] {PKG, PKG_N_MR1};
6647         int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
6648 
6649         mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
6650 
6651         verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
6652 
6653         mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
6654 
6655         verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
6656         verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
6657     }
6658 
6659     @Test
testNotificationHistory_addNoisyNotification()6660     public void testNotificationHistory_addNoisyNotification() throws Exception {
6661         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
6662                 null /* tvExtender */);
6663         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6664                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6665         waitForIdle();
6666 
6667         verify(mHistoryManager, times(1)).addNotification(any());
6668     }
6669 
6670     @Test
createConversationNotificationChannel()6671     public void createConversationNotificationChannel() throws Exception {
6672         NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
6673         original.setAllowBubbles(!original.canBubble());
6674         original.setShowBadge(!original.canShowBadge());
6675 
6676         Parcel parcel = Parcel.obtain();
6677         original.writeToParcel(parcel, 0);
6678         parcel.setDataPosition(0);
6679         NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
6680         assertEquals(original, orig);
6681         assertFalse(TextUtils.isEmpty(orig.getName()));
6682 
6683         mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6684                 orig)));
6685 
6686         mBinderService.createConversationNotificationChannelForPackage(
6687                 PKG, mUid, "key", orig, "friend");
6688 
6689         NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
6690                 PKG, 0, PKG, original.getId(), false, "friend");
6691 
6692         assertEquals(original.getName(), friendChannel.getName());
6693         assertEquals(original.getId(), friendChannel.getParentChannelId());
6694         assertEquals("friend", friendChannel.getConversationId());
6695         assertEquals(null, original.getConversationId());
6696         assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
6697         assertFalse(friendChannel.canBubble()); // can't be modified by app
6698         assertFalse(original.getId().equals(friendChannel.getId()));
6699         assertNotNull(friendChannel.getId());
6700     }
6701 
6702     @Test
deleteConversationNotificationChannels()6703     public void deleteConversationNotificationChannels() throws Exception {
6704         NotificationChannel messagesParent =
6705                 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
6706         Parcel msgParcel = Parcel.obtain();
6707         messagesParent.writeToParcel(msgParcel, 0);
6708         msgParcel.setDataPosition(0);
6709 
6710         NotificationChannel callsParent =
6711                 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
6712         Parcel callParcel = Parcel.obtain();
6713         callsParent.writeToParcel(callParcel, 0);
6714         callParcel.setDataPosition(0);
6715 
6716         mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6717                 messagesParent, callsParent)));
6718 
6719         String conversationId = "friend";
6720 
6721         mBinderService.createConversationNotificationChannelForPackage(
6722                 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
6723                 conversationId);
6724         mBinderService.createConversationNotificationChannelForPackage(
6725                 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
6726                 conversationId);
6727 
6728         NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
6729                 PKG, 0, PKG, messagesParent.getId(), false, conversationId);
6730         NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
6731                 PKG, 0, PKG, callsParent.getId(), false, conversationId);
6732 
6733         assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
6734         assertEquals(conversationId, messagesChild.getConversationId());
6735 
6736         assertEquals(callsParent.getId(), callsChild.getParentChannelId());
6737         assertEquals(conversationId, callsChild.getConversationId());
6738 
6739         mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
6740 
6741         assertNull(mBinderService.getConversationNotificationChannel(
6742                 PKG, 0, PKG, messagesParent.getId(), false, conversationId));
6743         assertNull(mBinderService.getConversationNotificationChannel(
6744                 PKG, 0, PKG, callsParent.getId(), false, conversationId));
6745     }
6746 
6747     @Test
testCorrectCategory_systemOn_appCannotTurnOff()6748     public void testCorrectCategory_systemOn_appCannotTurnOff() {
6749         int requested = 0;
6750         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6751 
6752         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6753                 system);
6754 
6755         assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
6756     }
6757 
6758     @Test
testCorrectCategory_systemOff_appTurnOff_noChanges()6759     public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
6760         int requested = PRIORITY_CATEGORY_CALLS;
6761         int system = PRIORITY_CATEGORY_CALLS;
6762 
6763         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6764                 system);
6765 
6766         assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6767     }
6768 
6769     @Test
testCorrectCategory_systemOn_appTurnOn_noChanges()6770     public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
6771         int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6772         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6773 
6774         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6775                 system);
6776 
6777         assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
6778     }
6779 
6780     @Test
testCorrectCategory_systemOff_appCannotTurnOn()6781     public void testCorrectCategory_systemOff_appCannotTurnOn() {
6782         int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6783         int system = PRIORITY_CATEGORY_CALLS;
6784 
6785         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6786                 system);
6787 
6788         assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6789     }
6790 
6791     @Test
testGetConversationsForPackage_hasShortcut()6792     public void testGetConversationsForPackage_hasShortcut() throws Exception {
6793         mService.setPreferencesHelper(mPreferencesHelper);
6794         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6795         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6796         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6797         channel1.setConversationId("parent1", "convo 1");
6798         convo1.setNotificationChannel(channel1);
6799         convos.add(convo1);
6800 
6801         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6802         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6803         channel2.setConversationId("parent1", "convo 2");
6804         convo2.setNotificationChannel(channel2);
6805         convos.add(convo2);
6806         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6807 
6808         ShortcutInfo si = mock(ShortcutInfo.class);
6809         when(si.getPackage()).thenReturn(PKG_P);
6810         when(si.getId()).thenReturn("convo");
6811         when(si.getUserId()).thenReturn(USER_SYSTEM);
6812         when(si.getLabel()).thenReturn("Hello");
6813         when(si.isLongLived()).thenReturn(true);
6814         when(si.isEnabled()).thenReturn(true);
6815         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6816         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6817                 anyString(), anyInt(), any())).thenReturn(true);
6818 
6819         List<ConversationChannelWrapper> conversations =
6820                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6821         assertEquals(si, conversations.get(0).getShortcutInfo());
6822         assertEquals(si, conversations.get(1).getShortcutInfo());
6823     }
6824 
6825     @Test
testGetConversationsForPackage_shortcut_notLongLived()6826     public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
6827         mService.setPreferencesHelper(mPreferencesHelper);
6828         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6829         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6830         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6831         channel1.setConversationId("parent1", "convo 1");
6832         convo1.setNotificationChannel(channel1);
6833         convos.add(convo1);
6834 
6835         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6836         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6837         channel2.setConversationId("parent1", "convo 2");
6838         convo2.setNotificationChannel(channel2);
6839         convos.add(convo2);
6840         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6841 
6842         ShortcutInfo si = mock(ShortcutInfo.class);
6843         when(si.getPackage()).thenReturn(PKG_P);
6844         when(si.getId()).thenReturn("convo");
6845         when(si.getUserId()).thenReturn(USER_SYSTEM);
6846         when(si.getLabel()).thenReturn("Hello");
6847         when(si.isLongLived()).thenReturn(false);
6848         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6849 
6850         List<ConversationChannelWrapper> conversations =
6851                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6852         assertNull(conversations.get(0).getShortcutInfo());
6853         assertNull(conversations.get(1).getShortcutInfo());
6854     }
6855 
6856     @Test
testGetConversationsForPackage_doesNotHaveShortcut()6857     public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
6858         mService.setPreferencesHelper(mPreferencesHelper);
6859         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6860         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6861         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6862         channel1.setConversationId("parent1", "convo 1");
6863         convo1.setNotificationChannel(channel1);
6864         convos.add(convo1);
6865 
6866         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6867         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6868         channel2.setConversationId("parent1", "convo 2");
6869         convo2.setNotificationChannel(channel2);
6870         convos.add(convo2);
6871         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6872         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
6873 
6874         List<ConversationChannelWrapper> conversations =
6875                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6876         assertNull(conversations.get(0).getShortcutInfo());
6877         assertNull(conversations.get(1).getShortcutInfo());
6878     }
6879 
6880     @Test
testShortcutHelperNull_doesntCrashEnqueue()6881     public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
6882         mService.setShortcutHelper(null);
6883         NotificationRecord nr =
6884                 generateMessageBubbleNotifRecord(mTestNotificationChannel,
6885                         "testShortcutHelperNull_doesntCrashEnqueue");
6886         try {
6887             mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6888                     nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6889             waitForIdle();
6890         } catch (Exception e) {
6891             fail(e.getMessage());
6892         }
6893     }
6894 
6895     @Test
testRecordMessages_invalidMsg()6896     public void testRecordMessages_invalidMsg() throws RemoteException {
6897         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6898                 null /* groupKey */, false /* isSummary */);
6899         nb.setShortcutId(null);
6900         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
6901                 "testRecordMessages_invalidMsg", mUid, 0, nb.build(),
6902                 UserHandle.getUserHandleForUid(mUid), null, 0);
6903         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6904 
6905         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
6906         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
6907                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6908         waitForIdle();
6909 
6910         assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
6911     }
6912 
6913     @Test
testRecordMessages_invalidMsg_notMessageStyle()6914     public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException {
6915         Notification.Builder nb = new Notification.Builder(mContext,
6916                 mTestNotificationChannel.getId())
6917                 .setContentTitle("foo")
6918                 .setShortcutId(null)
6919                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6920                 .setCategory(Notification.CATEGORY_MESSAGE);
6921         StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1,
6922                 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(),
6923                 UserHandle.getUserHandleForUid(mUid), null, 0);
6924         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6925 
6926         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
6927         mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(),
6928                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6929         waitForIdle();
6930 
6931         // PKG_O is allowed to be in conversation space b/c of override in
6932         // TestableNotificationManagerService
6933         assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid));
6934     }
6935 
6936     @Test
testRecordMessages_validMsg()6937     public void testRecordMessages_validMsg() throws RemoteException {
6938         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6939                 null /* groupKey */, false /* isSummary */);
6940         nb.setShortcutId(null);
6941         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
6942                 "testRecordMessages_validMsg", mUid, 0, nb.build(),
6943                 UserHandle.getUserHandleForUid(mUid), null, 0);
6944         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6945 
6946         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
6947                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6948         waitForIdle();
6949 
6950         assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
6951 
6952         nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6953                 "testRecordMessages_validMsg");
6954 
6955         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
6956                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6957         waitForIdle();
6958 
6959         assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid));
6960     }
6961 
6962     @Test
testRecordMessages_invalidMsg_afterValidMsg()6963     public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException {
6964         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6965                 "testRecordMessages_invalidMsg_afterValidMsg_1");
6966         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6967                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6968         waitForIdle();
6969         assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation());
6970 
6971         mBinderService.cancelAllNotifications(PKG, mUid);
6972         waitForIdle();
6973 
6974         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6975                 null /* groupKey */, false /* isSummary */);
6976         nb.setShortcutId(null);
6977         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6978                 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
6979                 UserHandle.getUserHandleForUid(mUid), null, 0);
6980          nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6981 
6982         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6983                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6984         waitForIdle();
6985 
6986         assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation());
6987     }
6988 
6989     @Test
testCanPostFgsWhenOverLimit()6990     public void testCanPostFgsWhenOverLimit() throws RemoteException {
6991         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
6992             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
6993                     i, null, false).getSbn();
6994             mBinderService.enqueueNotificationWithTag(PKG, PKG,
6995                     "testCanPostFgsWhenOverLimit",
6996                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
6997         }
6998 
6999         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
7000         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
7001         mBinderService.enqueueNotificationWithTag(PKG, PKG,
7002                 "testCanPostFgsWhenOverLimit - fgs over limit!",
7003                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
7004 
7005         waitForIdle();
7006 
7007         StatusBarNotification[] notifs =
7008                 mBinderService.getActiveNotifications(sbn.getPackageName());
7009         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
7010         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
7011                 mService.getNotificationRecordCount());
7012     }
7013 
7014     @Test
testCannotPostNonFgsWhenOverLimit()7015     public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
7016         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7017             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
7018                     i, null, false).getSbn();
7019             mBinderService.enqueueNotificationWithTag(PKG, PKG,
7020                     "testCanPostFgsWhenOverLimit",
7021                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
7022             waitForIdle();
7023         }
7024 
7025         final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
7026                 100, null, false).getSbn();
7027         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
7028         mBinderService.enqueueNotificationWithTag(PKG, PKG,
7029                 "testCanPostFgsWhenOverLimit - fgs over limit!",
7030                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
7031 
7032         final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
7033                 101, null, false).getSbn();
7034         mBinderService.enqueueNotificationWithTag(PKG, PKG,
7035                 "testCanPostFgsWhenOverLimit - non fgs over limit!",
7036                 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
7037 
7038         waitForIdle();
7039 
7040         StatusBarNotification[] notifs =
7041                 mBinderService.getActiveNotifications(sbn.getPackageName());
7042         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
7043         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
7044                 mService.getNotificationRecordCount());
7045     }
7046 }
7047