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