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