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