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.EXTRA_ALLOW_DURING_SETUP;
25 import static android.app.Notification.FLAG_AUTO_CANCEL;
26 import static android.app.Notification.FLAG_BUBBLE;
27 import static android.app.Notification.FLAG_CAN_COLORIZE;
28 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
29 import static android.app.Notification.FLAG_NO_CLEAR;
30 import static android.app.Notification.FLAG_ONGOING_EVENT;
31 import static android.app.Notification.FLAG_USER_INITIATED_JOB;
32 import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
33 import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
34 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
35 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
36 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
37 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
38 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
39 import static android.app.NotificationManager.IMPORTANCE_HIGH;
40 import static android.app.NotificationManager.IMPORTANCE_LOW;
41 import static android.app.NotificationManager.IMPORTANCE_MAX;
42 import static android.app.NotificationManager.IMPORTANCE_NONE;
43 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
44 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
45 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
46 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
47 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
48 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
49 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
50 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
51 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
52 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
53 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
54 import static android.app.PendingIntent.FLAG_IMMUTABLE;
55 import static android.app.PendingIntent.FLAG_MUTABLE;
56 import static android.app.PendingIntent.FLAG_ONE_SHOT;
57 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
58 import static android.content.pm.PackageManager.FEATURE_TELECOM;
59 import static android.content.pm.PackageManager.FEATURE_WATCH;
60 import static android.content.pm.PackageManager.PERMISSION_DENIED;
61 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
62 import static android.os.Build.VERSION_CODES.O_MR1;
63 import static android.os.Build.VERSION_CODES.P;
64 import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
65 import static android.os.PowerWhitelistManager.REASON_NOTIFICATION_SERVICE;
66 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
67 import static android.os.UserHandle.USER_SYSTEM;
68 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
69 import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
70 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
71 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
72 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
73 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
74 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
75 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
76 import static android.service.notification.NotificationListenerService.REASON_CANCEL;
77 import static android.service.notification.NotificationListenerService.REASON_LOCKDOWN;
78 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
79 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
80 import static android.view.Display.DEFAULT_DISPLAY;
81 import static android.view.Display.INVALID_DISPLAY;
82 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
83 
84 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE;
85 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI;
86 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.WAKE_LOCK_FOR_POSTING_NOTIFICATION;
87 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
88 import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
89 import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
90 import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
91 import static com.android.server.notification.NotificationManagerService.DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
92 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED;
93 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
94 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED;
95 
96 import static com.google.common.truth.Truth.assertThat;
97 import static com.google.common.truth.Truth.assertWithMessage;
98 
99 import static junit.framework.Assert.assertEquals;
100 import static junit.framework.Assert.assertFalse;
101 import static junit.framework.Assert.assertNotNull;
102 import static junit.framework.Assert.assertNotSame;
103 import static junit.framework.Assert.assertNull;
104 import static junit.framework.Assert.assertSame;
105 import static junit.framework.Assert.assertTrue;
106 import static junit.framework.Assert.fail;
107 
108 import static org.junit.Assert.assertNotEquals;
109 import static org.junit.Assert.assertThrows;
110 import static org.mockito.ArgumentMatchers.isNull;
111 import static org.mockito.Matchers.anyBoolean;
112 import static org.mockito.Matchers.anyLong;
113 import static org.mockito.Matchers.anyString;
114 import static org.mockito.Matchers.eq;
115 import static org.mockito.Mockito.any;
116 import static org.mockito.Mockito.anyInt;
117 import static org.mockito.Mockito.atLeastOnce;
118 import static org.mockito.Mockito.clearInvocations;
119 import static org.mockito.Mockito.doAnswer;
120 import static org.mockito.Mockito.doNothing;
121 import static org.mockito.Mockito.doThrow;
122 import static org.mockito.Mockito.inOrder;
123 import static org.mockito.Mockito.mock;
124 import static org.mockito.Mockito.never;
125 import static org.mockito.Mockito.reset;
126 import static org.mockito.Mockito.spy;
127 import static org.mockito.Mockito.timeout;
128 import static org.mockito.Mockito.times;
129 import static org.mockito.Mockito.verify;
130 import static org.mockito.Mockito.verifyNoMoreInteractions;
131 import static org.mockito.Mockito.verifyZeroInteractions;
132 import static org.mockito.Mockito.when;
133 
134 import static java.util.Collections.emptyList;
135 import static java.util.Collections.singletonList;
136 
137 import android.Manifest;
138 import android.annotation.Nullable;
139 import android.annotation.SuppressLint;
140 import android.annotation.UserIdInt;
141 import android.app.ActivityManager;
142 import android.app.ActivityManagerInternal;
143 import android.app.AlarmManager;
144 import android.app.AppOpsManager;
145 import android.app.AutomaticZenRule;
146 import android.app.IActivityManager;
147 import android.app.INotificationManager;
148 import android.app.ITransientNotification;
149 import android.app.IUriGrantsManager;
150 import android.app.Notification;
151 import android.app.Notification.MessagingStyle.Message;
152 import android.app.NotificationChannel;
153 import android.app.NotificationChannelGroup;
154 import android.app.NotificationManager;
155 import android.app.PendingIntent;
156 import android.app.Person;
157 import android.app.RemoteInput;
158 import android.app.RemoteInputHistoryItem;
159 import android.app.StatsManager;
160 import android.app.admin.DevicePolicyManagerInternal;
161 import android.app.usage.UsageStatsManagerInternal;
162 import android.companion.AssociationInfo;
163 import android.companion.ICompanionDeviceManager;
164 import android.content.BroadcastReceiver;
165 import android.content.ComponentName;
166 import android.content.ContentUris;
167 import android.content.Context;
168 import android.content.IIntentSender;
169 import android.content.Intent;
170 import android.content.IntentFilter;
171 import android.content.pm.ActivityInfo;
172 import android.content.pm.ApplicationInfo;
173 import android.content.pm.IPackageManager;
174 import android.content.pm.LauncherApps;
175 import android.content.pm.PackageManager;
176 import android.content.pm.PackageManagerInternal;
177 import android.content.pm.ParceledListSlice;
178 import android.content.pm.ShortcutInfo;
179 import android.content.pm.ShortcutServiceInternal;
180 import android.content.pm.UserInfo;
181 import android.content.pm.VersionedPackage;
182 import android.content.res.Resources;
183 import android.graphics.Color;
184 import android.graphics.drawable.Icon;
185 import android.media.AudioManager;
186 import android.media.IRingtonePlayer;
187 import android.media.session.MediaSession;
188 import android.net.Uri;
189 import android.os.Binder;
190 import android.os.Build;
191 import android.os.Bundle;
192 import android.os.IBinder;
193 import android.os.Looper;
194 import android.os.Parcel;
195 import android.os.Parcelable;
196 import android.os.PowerManager;
197 import android.os.PowerManager.WakeLock;
198 import android.os.Process;
199 import android.os.RemoteException;
200 import android.os.SystemClock;
201 import android.os.UserHandle;
202 import android.os.UserManager;
203 import android.os.WorkSource;
204 import android.permission.PermissionManager;
205 import android.provider.DeviceConfig;
206 import android.provider.MediaStore;
207 import android.provider.Settings;
208 import android.service.notification.Adjustment;
209 import android.service.notification.ConversationChannelWrapper;
210 import android.service.notification.NotificationListenerFilter;
211 import android.service.notification.NotificationListenerService;
212 import android.service.notification.NotificationRankingUpdate;
213 import android.service.notification.NotificationStats;
214 import android.service.notification.StatusBarNotification;
215 import android.service.notification.ZenPolicy;
216 import android.telecom.TelecomManager;
217 import android.telephony.TelephonyManager;
218 import android.test.suitebuilder.annotation.SmallTest;
219 import android.testing.AndroidTestingRunner;
220 import android.testing.TestableLooper;
221 import android.testing.TestableLooper.RunWithLooper;
222 import android.testing.TestablePermissions;
223 import android.testing.TestableResources;
224 import android.text.Html;
225 import android.text.TextUtils;
226 import android.util.ArrayMap;
227 import android.util.ArraySet;
228 import android.util.AtomicFile;
229 import android.util.Pair;
230 import android.util.Xml;
231 import android.widget.RemoteViews;
232 
233 import androidx.test.InstrumentationRegistry;
234 
235 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
236 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag;
237 import com.android.internal.config.sysui.TestableFlagResolver;
238 import com.android.internal.logging.InstanceIdSequence;
239 import com.android.internal.logging.InstanceIdSequenceFake;
240 import com.android.internal.messages.nano.SystemMessageProto;
241 import com.android.internal.statusbar.NotificationVisibility;
242 import com.android.modules.utils.TypedXmlPullParser;
243 import com.android.modules.utils.TypedXmlSerializer;
244 import com.android.server.DeviceIdleInternal;
245 import com.android.server.LocalServices;
246 import com.android.server.SystemService;
247 import com.android.server.SystemService.TargetUser;
248 import com.android.server.UiServiceTestCase;
249 import com.android.server.job.JobSchedulerInternal;
250 import com.android.server.lights.LightsManager;
251 import com.android.server.lights.LogicalLight;
252 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
253 import com.android.server.notification.NotificationManagerService.NotificationListeners;
254 import com.android.server.notification.NotificationManagerService.PostNotificationTracker;
255 import com.android.server.notification.NotificationManagerService.PostNotificationTrackerFactory;
256 import com.android.server.pm.PackageManagerService;
257 import com.android.server.pm.UserManagerInternal;
258 import com.android.server.policy.PermissionPolicyInternal;
259 import com.android.server.statusbar.StatusBarManagerInternal;
260 import com.android.server.uri.UriGrantsManagerInternal;
261 import com.android.server.utils.quota.MultiRateLimiter;
262 import com.android.server.wm.ActivityTaskManagerInternal;
263 import com.android.server.wm.WindowManagerInternal;
264 
265 import com.google.android.collect.Lists;
266 import com.google.common.collect.ImmutableList;
267 
268 import org.junit.After;
269 import org.junit.Assert;
270 import org.junit.Before;
271 import org.junit.Test;
272 import org.junit.runner.RunWith;
273 import org.mockito.ArgumentCaptor;
274 import org.mockito.ArgumentMatcher;
275 import org.mockito.ArgumentMatchers;
276 import org.mockito.InOrder;
277 import org.mockito.Mock;
278 import org.mockito.MockitoAnnotations;
279 import org.mockito.invocation.InvocationOnMock;
280 import org.mockito.stubbing.Answer;
281 
282 import java.io.BufferedInputStream;
283 import java.io.BufferedOutputStream;
284 import java.io.ByteArrayInputStream;
285 import java.io.ByteArrayOutputStream;
286 import java.io.File;
287 import java.io.FileOutputStream;
288 import java.util.ArrayList;
289 import java.util.Arrays;
290 import java.util.Collections;
291 import java.util.List;
292 import java.util.Map;
293 import java.util.concurrent.CountDownLatch;
294 import java.util.function.Consumer;
295 
296 
297 @SmallTest
298 @RunWith(AndroidTestingRunner.class)
299 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
300 @RunWithLooper
301 public class NotificationManagerServiceTest extends UiServiceTestCase {
302     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
303     private static final String TEST_PACKAGE = "The.name.is.Package.Test.Package";
304     private static final String PKG_NO_CHANNELS = "com.example.no.channels";
305     private static final int TEST_TASK_ID = 1;
306     private static final int UID_HEADLESS = 1_000_000;
307     private static final int TOAST_DURATION = 2_000;
308     private static final int SECONDARY_DISPLAY_ID = 42;
309 
310     private final int mUid = Binder.getCallingUid();
311     private final @UserIdInt int mUserId = UserHandle.getUserId(mUid);
312 
313     private TestableNotificationManagerService mService;
314     private INotificationManager mBinderService;
315     private NotificationManagerInternal mInternalService;
316     private ShortcutHelper mShortcutHelper;
317     @Mock
318     private IPackageManager mPackageManager;
319     @Mock
320     private PackageManager mPackageManagerClient;
321     @Mock
322     private PackageManagerInternal mPackageManagerInternal;
323     @Mock
324     private PermissionPolicyInternal mPermissionPolicyInternal;
325     @Mock
326     private WindowManagerInternal mWindowManagerInternal;
327     @Mock
328     private PermissionHelper mPermissionHelper;
329     private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();
330     private final String PKG = mContext.getPackageName();
331     private TestableLooper mTestableLooper;
332     @Mock
333     private RankingHelper mRankingHelper;
334     @Mock private PreferencesHelper mPreferencesHelper;
335     AtomicFile mPolicyFile;
336     File mFile;
337     @Mock
338     private NotificationUsageStats mUsageStats;
339     @Mock
340     private UsageStatsManagerInternal mAppUsageStats;
341     @Mock
342     private AudioManager mAudioManager;
343     @Mock
344     private LauncherApps mLauncherApps;
345     @Mock
346     private ShortcutServiceInternal mShortcutServiceInternal;
347     @Mock
348     private UserManager mUserManager;
349     @Mock
350     ActivityManager mActivityManager;
351     @Mock
352     TelecomManager mTelecomManager;
353     @Mock
354     Resources mResources;
355     @Mock
356     RankingHandler mRankingHandler;
357     @Mock
358     ActivityManagerInternal mAmi;
359     @Mock
360     JobSchedulerInternal mJsi;
361     @Mock
362     private Looper mMainLooper;
363     @Mock
364     private NotificationManager mMockNm;
365     @Mock
366     private PermissionManager mPermissionManager;
367     @Mock
368     private DevicePolicyManagerInternal mDevicePolicyManager;
369     @Mock
370     private PowerManager mPowerManager;
371     private final ArrayList<WakeLock> mAcquiredWakeLocks = new ArrayList<>();
372     private final TestPostNotificationTrackerFactory mPostNotificationTrackerFactory =
373             new TestPostNotificationTrackerFactory();
374 
375     @Mock
376     IIntentSender pi1;
377 
378     private static final int MAX_POST_DELAY = 1000;
379 
380     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
381             TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
382 
383     private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
384 
385     private static final String VALID_CONVO_SHORTCUT_ID = "shortcut";
386     private static final String SEARCH_SELECTOR_PKG = "searchSelector";
387     @Mock
388     private NotificationListeners mListeners;
389     @Mock
390     private NotificationListenerFilter mNlf;
391     @Mock private NotificationAssistants mAssistants;
392     @Mock private ConditionProviders mConditionProviders;
393     private ManagedServices.ManagedServiceInfo mListener;
394     @Mock private ICompanionDeviceManager mCompanionMgr;
395     @Mock SnoozeHelper mSnoozeHelper;
396     @Mock GroupHelper mGroupHelper;
397     @Mock
398     IBinder mPermOwner;
399     @Mock
400     IActivityManager mAm;
401     @Mock
402     ActivityTaskManagerInternal mAtm;
403     @Mock
404     IUriGrantsManager mUgm;
405     @Mock
406     UriGrantsManagerInternal mUgmInternal;
407     @Mock
408     AppOpsManager mAppOpsManager;
409     private AppOpsManager.OnOpChangedListener mOnPermissionChangeListener;
410     @Mock
411     private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
412             mNotificationAssistantAccessGrantedCallback;
413     @Mock
414     UserManager mUm;
415     @Mock
416     UserManagerInternal mUmInternal;
417     @Mock
418     NotificationHistoryManager mHistoryManager;
419     @Mock
420     StatsManager mStatsManager;
421     @Mock
422     AlarmManager mAlarmManager;
423     @Mock
424     MultiRateLimiter mToastRateLimiter;
425     BroadcastReceiver mPackageIntentReceiver;
426     BroadcastReceiver mUserSwitchIntentReceiver;
427     NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
428     TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;
429 
430     TestableFlagResolver mTestFlagResolver = new TestableFlagResolver();
431 
432     private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
433             1 << 30);
434     @Mock
435     StatusBarManagerInternal mStatusBar;
436 
437     private NotificationManagerService.WorkerHandler mWorkerHandler;
438 
439     private class TestableToastCallback extends ITransientNotification.Stub {
440         @Override
show(IBinder windowToken)441         public void show(IBinder windowToken) {
442         }
443 
444         @Override
hide()445         public void hide() {
446         }
447     }
448 
449     private class TestPostNotificationTrackerFactory implements PostNotificationTrackerFactory {
450 
451         private final List<PostNotificationTracker> mCreatedTrackers = new ArrayList<>();
452 
453         @Override
newTracker(@ullable WakeLock optionalWakeLock)454         public PostNotificationTracker newTracker(@Nullable WakeLock optionalWakeLock) {
455             PostNotificationTracker tracker = PostNotificationTrackerFactory.super.newTracker(
456                     optionalWakeLock);
457             mCreatedTrackers.add(tracker);
458             return tracker;
459         }
460     }
461 
462     @Before
setUp()463     public void setUp() throws Exception {
464         // Shell permisssions will override permissions of our app, so add all necessary permissions
465         // for this test here:
466         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
467                 "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG",
468                 "android.permission.READ_DEVICE_CONFIG",
469                 "android.permission.READ_CONTACTS");
470 
471         MockitoAnnotations.initMocks(this);
472 
473         DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
474         when(deviceIdleInternal.getNotificationAllowlistDuration()).thenReturn(3000L);
475 
476         LocalServices.removeServiceForTest(UserManagerInternal.class);
477         LocalServices.addService(UserManagerInternal.class, mUmInternal);
478         LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
479         LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
480         LocalServices.removeServiceForTest(WindowManagerInternal.class);
481         LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
482         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
483         LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
484         LocalServices.removeServiceForTest(DeviceIdleInternal.class);
485         LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
486         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
487         LocalServices.addService(ActivityManagerInternal.class, mAmi);
488         LocalServices.removeServiceForTest(JobSchedulerInternal.class);
489         LocalServices.addService(JobSchedulerInternal.class, mJsi);
490         LocalServices.removeServiceForTest(PackageManagerInternal.class);
491         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
492         LocalServices.removeServiceForTest(PermissionPolicyInternal.class);
493         LocalServices.addService(PermissionPolicyInternal.class, mPermissionPolicyInternal);
494         mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
495         mContext.addMockSystemService(NotificationManager.class, mMockNm);
496 
497         doNothing().when(mContext).sendBroadcastAsUser(any(), any());
498         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
499 
500         setDpmAppOppsExemptFromDismissal(false);
501 
502         mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
503                 mNotificationInstanceIdSequence);
504 
505         // Use this testable looper.
506         mTestableLooper = TestableLooper.get(this);
507         // MockPackageManager - default returns ApplicationInfo with matching calling UID
508         mContext.setMockPackageManager(mPackageManagerClient);
509 
510         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt()))
511                 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
512                     Object[] args = invocation.getArguments();
513                     return getApplicationInfo((String) args[0], mUid);
514                 });
515         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
516                 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
517                     Object[] args = invocation.getArguments();
518                     return getApplicationInfo((String) args[0], mUid);
519                 });
520         when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
521         when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenAnswer(
522                 (Answer<Boolean>) invocation -> {
523                     Object[] args = invocation.getArguments();
524                     return (int) args[1] == mUid;
525                 });
526         final LightsManager mockLightsManager = mock(LightsManager.class);
527         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
528         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
529         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
530         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
531         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
532         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
533         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt()))
534                 .thenReturn(INVALID_TASK_ID);
535         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
536         when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});
537 
538         when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true);
539 
540         ActivityManager.AppTask task = mock(ActivityManager.AppTask.class);
541         List<ActivityManager.AppTask> taskList = new ArrayList<>();
542         ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo();
543         taskInfo.taskId = TEST_TASK_ID;
544         when(task.getTaskInfo()).thenReturn(taskInfo);
545         taskList.add(task);
546         when(mAtm.getAppTasks(anyString(), anyInt())).thenReturn(taskList);
547 
548         // write to a test file; the system file isn't readable from tests
549         mFile = new File(mContext.getCacheDir(), "test.xml");
550         mFile.createNewFile();
551         final String preupgradeXml = "<notification-policy></notification-policy>";
552         mPolicyFile = new AtomicFile(mFile);
553         FileOutputStream fos = mPolicyFile.startWrite();
554         fos.write(preupgradeXml.getBytes());
555         mPolicyFile.finishWrite(fos);
556 
557         // Setup managed services
558         when(mNlf.isTypeAllowed(anyInt())).thenReturn(true);
559         when(mNlf.isPackageAllowed(any())).thenReturn(true);
560         when(mNlf.isPackageAllowed(null)).thenReturn(true);
561         when(mListeners.getNotificationListenerFilter(any())).thenReturn(mNlf);
562         mListener = mListeners.new ManagedServiceInfo(
563                 null, new ComponentName(PKG, "test_class"),
564                 mUserId, true, null, 0, 123);
565         ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
566         ArraySet<ComponentName> components = new ArraySet<>();
567         components.add(defaultComponent);
568         when(mListeners.getDefaultComponents()).thenReturn(components);
569         when(mConditionProviders.getDefaultPackages())
570                 .thenReturn(new ArraySet<>(Arrays.asList("config")));
571         when(mAssistants.getDefaultComponents()).thenReturn(components);
572         when(mAssistants.queryPackageForServices(
573                 anyString(), anyInt(), anyInt())).thenReturn(components);
574         when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener);
575         ManagedServices.Config listenerConfig = new ManagedServices.Config();
576         listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
577         when(mListeners.getConfig()).thenReturn(listenerConfig);
578         ManagedServices.Config assistantConfig = new ManagedServices.Config();
579         assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
580         when(mAssistants.getConfig()).thenReturn(assistantConfig);
581         ManagedServices.Config dndConfig = new ManagedServices.Config();
582         dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
583         when(mConditionProviders.getConfig()).thenReturn(dndConfig);
584 
585         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
586 
587         // Use the real PowerManager to back up the mock w.r.t. creating WakeLocks.
588         // This is because 1) we need a mock to verify() calls and tracking the created WakeLocks,
589         // but 2) PowerManager and WakeLock perform their own checks (e.g. correct arguments, don't
590         // call release twice, etc) and we want the test to fail if such misuse happens, too.
591         PowerManager realPowerManager = mContext.getSystemService(PowerManager.class);
592         when(mPowerManager.newWakeLock(anyInt(), anyString())).then(
593                 (Answer<WakeLock>) invocation -> {
594                     WakeLock wl = realPowerManager.newWakeLock(invocation.getArgument(0),
595                             invocation.getArgument(1));
596                     mAcquiredWakeLocks.add(wl);
597                     return wl;
598                 });
599         mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
600         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
601                 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false);
602 
603         // apps allowed as convos
604         mService.setStringArrayResourceValue(PKG_O);
605 
606         TestableResources tr = mContext.getOrCreateTestableResources();
607         tr.addOverride(com.android.internal.R.string.config_defaultSearchSelectorPackageName,
608                 SEARCH_SELECTOR_PKG);
609 
610         doAnswer(invocation -> {
611             mOnPermissionChangeListener = invocation.getArgument(2);
612             return null;
613         }).when(mAppOpsManager).startWatchingMode(eq(AppOpsManager.OP_POST_NOTIFICATION), any(),
614                 any());
615         when(mUmInternal.isUserInitialized(anyInt())).thenReturn(true);
616 
617         mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper()));
618         mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient,
619                 mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr,
620                 mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm,
621                 mAppUsageStats, mDevicePolicyManager, mUgm, mUgmInternal,
622                 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
623                 mock(TelephonyManager.class),
624                 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
625                 mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager,
626                 mPowerManager, mPostNotificationTrackerFactory);
627         // Return first true for RoleObserver main-thread check
628         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
629         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
630         verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
631         mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
632         verify(mHistoryManager).onBootPhaseAppsCanStart();
633 
634         mService.setAudioManager(mAudioManager);
635 
636         mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext);
637         mService.setStrongAuthTracker(mStrongAuthTracker);
638 
639         mShortcutHelper = mService.getShortcutHelper();
640         mShortcutHelper.setLauncherApps(mLauncherApps);
641         mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
642         mShortcutHelper.setUserManager(mUserManager);
643 
644         // Capture PackageIntentReceiver
645         ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
646                 ArgumentCaptor.forClass(BroadcastReceiver.class);
647         ArgumentCaptor<IntentFilter> intentFilterCaptor =
648                 ArgumentCaptor.forClass(IntentFilter.class);
649 
650         verify(mContext, atLeastOnce()).registerReceiverAsUser(broadcastReceiverCaptor.capture(),
651                 any(), intentFilterCaptor.capture(), any(), any());
652         verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(),
653                 intentFilterCaptor.capture());
654         List<BroadcastReceiver> broadcastReceivers = broadcastReceiverCaptor.getAllValues();
655         List<IntentFilter> intentFilters = intentFilterCaptor.getAllValues();
656 
657         for (int i = 0; i < intentFilters.size(); i++) {
658             final IntentFilter filter = intentFilters.get(i);
659             if (filter.hasAction(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED)
660                     && filter.hasAction(Intent.ACTION_PACKAGES_UNSUSPENDED)
661                     && filter.hasAction(Intent.ACTION_PACKAGES_SUSPENDED)) {
662                 mPackageIntentReceiver = broadcastReceivers.get(i);
663             }
664             if (filter.hasAction(Intent.ACTION_USER_SWITCHED)) {
665                 mUserSwitchIntentReceiver = broadcastReceivers.get(i);
666             }
667         }
668         assertNotNull("package intent receiver should exist", mPackageIntentReceiver);
669         assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver);
670 
671         // Pretend the shortcut exists
672         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
673         ShortcutInfo info = mock(ShortcutInfo.class);
674         when(info.getPackage()).thenReturn(PKG);
675         when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID);
676         when(info.getUserId()).thenReturn(USER_SYSTEM);
677         when(info.isLongLived()).thenReturn(true);
678         when(info.isEnabled()).thenReturn(true);
679         shortcutInfos.add(info);
680         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
681         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
682                 anyString(), anyInt(), any())).thenReturn(true);
683         when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
684         mockIsUserVisible(DEFAULT_DISPLAY, true);
685         mockIsVisibleBackgroundUsersSupported(false);
686 
687         // Set the testable bubble extractor
688         RankingHelper rankingHelper = mService.getRankingHelper();
689         BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
690         extractor.setActivityManager(mActivityManager);
691 
692         // Tests call directly into the Binder.
693         mBinderService = mService.getBinderService();
694         mInternalService = mService.getInternalService();
695 
696         mBinderService.createNotificationChannels(
697                 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
698         mBinderService.createNotificationChannels(
699                 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
700         mBinderService.createNotificationChannels(
701                 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
702         assertNotNull(mBinderService.getNotificationChannel(
703                 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
704         clearInvocations(mRankingHandler);
705         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
706 
707         mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false);
708         mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false);
709 
710         var checker = mock(TestableNotificationManagerService.ComponentPermissionChecker.class);
711         mService.permissionChecker = checker;
712         when(checker.check(anyString(), anyInt(), anyInt(), anyBoolean()))
713                 .thenReturn(PackageManager.PERMISSION_DENIED);
714     }
715 
716     @After
assertNotificationRecordLoggerCallsValid()717     public void assertNotificationRecordLoggerCallsValid() {
718         waitForIdle(); // Finish async work, including all logging calls done by Runnables.
719         for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
720             if (call.wasLogged) {
721                 assertNotNull(call.event);
722                 if (call.event == NOTIFICATION_POSTED || call.event == NOTIFICATION_UPDATED) {
723                     assertThat(call.postDurationMillisLogged).isGreaterThan(0);
724                 } else {
725                     assertThat(call.postDurationMillisLogged).isNull();
726                 }
727             }
728         }
729         assertThat(mNotificationRecordLogger.getPendingLogs()).isEmpty();
730     }
731 
732     @After
assertAllTrackersFinishedOrCancelled()733     public void assertAllTrackersFinishedOrCancelled() {
734         waitForIdle(); // Finish async work.
735         // Verify that no trackers were left dangling.
736         for (PostNotificationTracker tracker : mPostNotificationTrackerFactory.mCreatedTrackers) {
737             assertThat(tracker.isOngoing()).isFalse();
738         }
739         mPostNotificationTrackerFactory.mCreatedTrackers.clear();
740     }
741 
742     @After
assertAllWakeLocksReleased()743     public void assertAllWakeLocksReleased() {
744         waitForIdle(); // Finish async work.
745         for (WakeLock wakeLock : mAcquiredWakeLocks) {
746             assertThat(wakeLock.isHeld()).isFalse();
747         }
748     }
749 
750     @After
tearDown()751     public void tearDown() throws Exception {
752         if (mFile != null) mFile.delete();
753         clearDeviceConfig();
754 
755         try {
756             mService.onDestroy();
757         } catch (IllegalStateException | IllegalArgumentException e) {
758             // can throw if a broadcast receiver was never registered
759         }
760 
761         InstrumentationRegistry.getInstrumentation()
762                 .getUiAutomation().dropShellPermissionIdentity();
763         // Remove scheduled messages that would be processed when the test is already done, and
764         // could cause issues, for example, messages that remove/cancel shown toasts (this causes
765         // problematic interactions with mocks when they're no longer working as expected).
766         mWorkerHandler.removeCallbacksAndMessages(null);
767     }
768 
simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid)769     private void simulatePackageSuspendBroadcast(boolean suspend, String pkg,
770             int uid) {
771         // mimics receive broadcast that package is (un)suspended
772         // but does not actually (un)suspend the package
773         final Bundle extras = new Bundle();
774         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
775                 new String[]{pkg});
776         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid});
777 
778         final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED
779                 : Intent.ACTION_PACKAGES_UNSUSPENDED;
780         final Intent intent = new Intent(action);
781         intent.putExtras(extras);
782 
783         mPackageIntentReceiver.onReceive(getContext(), intent);
784     }
785 
simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids)786     private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) {
787         // mimics receive broadcast that package is (un)distracting
788         // but does not actually register that info with packagemanager
789         final Bundle extras = new Bundle();
790         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs);
791         extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag);
792         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids);
793 
794         final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED);
795         intent.putExtras(extras);
796 
797         mPackageIntentReceiver.onReceive(getContext(), intent);
798     }
799 
generateResetComponentValues()800     private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
801         ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
802         changed.put(true, new ArrayList<>());
803         changed.put(false, new ArrayList<>());
804         return changed;
805     }
getApplicationInfo(String pkg, int uid)806     private ApplicationInfo getApplicationInfo(String pkg, int uid) {
807         final ApplicationInfo applicationInfo = new ApplicationInfo();
808         applicationInfo.uid = uid;
809         switch (pkg) {
810             case PKG_N_MR1:
811                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
812                 break;
813             case PKG_O:
814                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
815                 break;
816             case PKG_P:
817                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
818                 break;
819             default:
820                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
821                 break;
822         }
823         return applicationInfo;
824     }
825 
waitForIdle()826     public void waitForIdle() {
827         mTestableLooper.processAllMessages();
828     }
829 
setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, int pkgPref, boolean channelEnabled)830     private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
831             int pkgPref, boolean channelEnabled) {
832         Settings.Secure.putInt(mContext.getContentResolver(),
833                 Settings.Secure.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
834         mService.mPreferencesHelper.updateBubblesEnabled();
835         assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled(
836                 mock(UserHandle.class)));
837         try {
838             mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
839         } catch (RemoteException e) {
840             e.printStackTrace();
841         }
842         mTestNotificationChannel.setAllowBubbles(channelEnabled);
843     }
844 
generateSbn(String pkg, int uid, long postTime, int userId)845     private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
846         Notification.Builder nb = new Notification.Builder(mContext, "a")
847                 .setContentTitle("foo")
848                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
849         StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
850                 "tag" + System.currentTimeMillis(), uid, 0,
851                 nb.build(), new UserHandle(userId), null, postTime);
852         return sbn;
853     }
854 
generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)855     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
856             String groupKey, boolean isSummary) {
857         return generateNotificationRecord(channel, id, "tag" + System.currentTimeMillis(), groupKey,
858                 isSummary);
859     }
860 
generateNotificationRecord(NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)861     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
862             String tag, String groupKey, boolean isSummary) {
863         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
864                 .setContentTitle("foo")
865                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
866                 .setGroup(groupKey)
867                 .setGroupSummary(isSummary);
868         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
869                 tag, mUid, 0,
870                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
871         return new NotificationRecord(mContext, sbn, channel);
872     }
873 
generateNotificationRecord(NotificationChannel channel)874     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
875         return generateNotificationRecord(channel, null);
876     }
877 
generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)878     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
879             Notification.TvExtender extender) {
880         if (channel == null) {
881             channel = mTestNotificationChannel;
882         }
883         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
884                 .setContentTitle("foo")
885                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
886                 .addAction(new Notification.Action.Builder(null, "test", null).build());
887         if (extender != null) {
888             nb.extend(extender);
889         }
890         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
891                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
892         return new NotificationRecord(mContext, sbn, channel);
893     }
894 
generateNotificationRecord(NotificationChannel channel, int userId)895     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
896         return generateNotificationRecord(channel, 1, userId);
897     }
898 
generateNotificationRecord(NotificationChannel channel, int id, int userId)899     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
900             int userId) {
901         if (channel == null) {
902             channel = mTestNotificationChannel;
903         }
904         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
905                 .setContentTitle("foo")
906                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
907         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
908                 nb.build(), new UserHandle(userId), null, 0);
909         return new NotificationRecord(mContext, sbn, channel);
910     }
911 
generateMessageBubbleNotifRecord(NotificationChannel channel, String tag)912     private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
913             String tag) {
914         return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
915     }
916 
generateMessageBubbleNotifRecord(boolean addMetadata, NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)917     private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
918             NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
919         if (channel == null) {
920             channel = mTestNotificationChannel;
921         }
922         if (tag == null) {
923             tag = "tag";
924         }
925         Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
926         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
927                 tag, mUid, 0,
928                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
929         return new NotificationRecord(mContext, sbn, channel);
930     }
931 
getSignalExtractorSideEffects()932     private Map<String, Answer> getSignalExtractorSideEffects() {
933         Map<String, Answer> answers = new ArrayMap<>();
934 
935         answers.put("override group key", invocationOnMock -> {
936             ((NotificationRecord) invocationOnMock.getArguments()[0])
937                     .setOverrideGroupKey("bananas");
938             return null;
939         });
940         answers.put("override people", invocationOnMock -> {
941             ((NotificationRecord) invocationOnMock.getArguments()[0])
942                     .setPeopleOverride(new ArrayList<>());
943             return null;
944         });
945         answers.put("snooze criteria", invocationOnMock -> {
946             ((NotificationRecord) invocationOnMock.getArguments()[0])
947                     .setSnoozeCriteria(new ArrayList<>());
948             return null;
949         });
950         answers.put("notification channel", invocationOnMock -> {
951             ((NotificationRecord) invocationOnMock.getArguments()[0])
952                     .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
953             return null;
954         });
955         answers.put("badging", invocationOnMock -> {
956             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
957             r.setShowBadge(!r.canShowBadge());
958             return null;
959         });
960         answers.put("bubbles", invocationOnMock -> {
961             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
962             r.setAllowBubble(!r.canBubble());
963             return null;
964         });
965         answers.put("package visibility", invocationOnMock -> {
966             ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
967                     Notification.VISIBILITY_SECRET);
968             return null;
969         });
970 
971         return answers;
972     }
973 
clearDeviceConfig()974     private void clearDeviceConfig() {
975         DeviceConfig.resetToDefaults(
976                 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
977     }
978 
setDefaultAssistantInDeviceConfig(String componentName)979     private void setDefaultAssistantInDeviceConfig(String componentName) {
980         DeviceConfig.setProperty(
981                 DeviceConfig.NAMESPACE_SYSTEMUI,
982                 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
983                 componentName,
984                 false);
985     }
986 
getMessageStyleNotifBuilder(boolean addBubbleMetadata, String groupKey, boolean isSummary)987     private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
988             String groupKey, boolean isSummary) {
989         // Give it a person
990         Person person = new Person.Builder()
991                 .setName("bubblebot")
992                 .build();
993         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
994         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
995                 new Intent().setPackage(mContext.getPackageName()),
996                 PendingIntent.FLAG_MUTABLE);
997         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
998         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
999                 inputIntent).addRemoteInput(remoteInput)
1000                 .build();
1001         // Make it messaging style
1002         Notification.Builder nb = new Notification.Builder(mContext,
1003                 mTestNotificationChannel.getId())
1004                 .setContentTitle("foo")
1005                 .setStyle(new Notification.MessagingStyle(person)
1006                         .setConversationTitle("Bubble Chat")
1007                         .addMessage("Hello?",
1008                                 SystemClock.currentThreadTimeMillis() - 300000, person)
1009                         .addMessage("Is it me you're looking for?",
1010                                 SystemClock.currentThreadTimeMillis(), person)
1011                 )
1012                 .setActions(replyAction)
1013                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1014                 .setShortcutId(VALID_CONVO_SHORTCUT_ID)
1015                 .setGroupSummary(isSummary);
1016         if (groupKey != null) {
1017             nb.setGroup(groupKey);
1018         }
1019         if (addBubbleMetadata) {
1020             nb.setBubbleMetadata(getBubbleMetadata());
1021         }
1022         return nb;
1023     }
1024 
getBubbleMetadata()1025     private Notification.BubbleMetadata getBubbleMetadata() {
1026         PendingIntent pendingIntent = mock(PendingIntent.class);
1027         Intent intent = mock(Intent.class);
1028         when(pendingIntent.getIntent()).thenReturn(intent);
1029         when(pendingIntent.getTarget()).thenReturn(pi1);
1030 
1031         ActivityInfo info = new ActivityInfo();
1032         info.resizeMode = RESIZE_MODE_RESIZEABLE;
1033         when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
1034 
1035         return new Notification.BubbleMetadata.Builder(
1036                 pendingIntent,
1037                 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
1038                 .build();
1039     }
1040 
addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)1041     private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
1042             throws RemoteException {
1043 
1044         String groupKey = "BUBBLE_GROUP";
1045 
1046         // Notification that has bubble metadata
1047         NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
1048                 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
1049 
1050         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
1051                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
1052                 nrBubble.getSbn().getUserId());
1053         waitForIdle();
1054 
1055         // Make sure we are a bubble
1056         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
1057         assertEquals(1, notifsAfter.length);
1058         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
1059 
1060         // Notification without bubble metadata
1061         NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
1062                 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
1063 
1064         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
1065                 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
1066                 nrPlain.getSbn().getUserId());
1067         waitForIdle();
1068 
1069         notifsAfter = mBinderService.getActiveNotifications(PKG);
1070         assertEquals(2, notifsAfter.length);
1071 
1072         // Summary notification for both of those
1073         NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
1074                 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
1075 
1076         if (summaryAutoCancel) {
1077             nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
1078         }
1079         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
1080                 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
1081                 nrSummary.getSbn().getUserId());
1082         waitForIdle();
1083 
1084         notifsAfter = mBinderService.getActiveNotifications(PKG);
1085         assertEquals(3, notifsAfter.length);
1086 
1087         return nrSummary;
1088     }
1089 
1090     @Test
testLimitTimeOutBroadcast()1091     public void testLimitTimeOutBroadcast() {
1092         NotificationChannel channel = new NotificationChannel("id", "name",
1093                 NotificationManager.IMPORTANCE_HIGH);
1094         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
1095                 .setContentTitle("foo")
1096                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1097                 .setTimeoutAfter(1);
1098 
1099         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
1100                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
1101         NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
1102 
1103         mService.scheduleTimeoutLocked(r);
1104         ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
1105         verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
1106         assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
1107                 captor.getValue().getIntent().getPackage());
1108     }
1109 
1110     @Test
testDefaultAssistant_overrideDefault()1111     public void testDefaultAssistant_overrideDefault() {
1112         final int userId = mContext.getUserId();
1113         final String testComponent = "package/class";
1114         final List<UserInfo> userInfos = new ArrayList<>();
1115         userInfos.add(new UserInfo(userId, "", 0));
1116         final ArraySet<ComponentName> validAssistants = new ArraySet<>();
1117         validAssistants.add(ComponentName.unflattenFromString(testComponent));
1118         when(mActivityManager.isLowRamDevice()).thenReturn(false);
1119         when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
1120                 .thenReturn(validAssistants);
1121         when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
1122         when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
1123 
1124         mService.setDefaultAssistantForUser(userId);
1125 
1126         verify(mAssistants).setPackageOrComponentEnabled(
1127                 eq(testComponent), eq(userId), eq(true), eq(true), eq(false));
1128     }
1129 
1130     @Test
testCreateNotificationChannels_SingleChannel()1131     public void testCreateNotificationChannels_SingleChannel() throws Exception {
1132         final NotificationChannel channel =
1133                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1134         mBinderService.createNotificationChannels(PKG,
1135                 new ParceledListSlice(Arrays.asList(channel)));
1136         final NotificationChannel createdChannel =
1137                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1138         assertTrue(createdChannel != null);
1139     }
1140 
1141     @Test
testCreateNotificationChannels_NullChannelThrowsException()1142     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
1143         try {
1144             mBinderService.createNotificationChannels(PKG,
1145                     new ParceledListSlice(Arrays.asList((Object[])null)));
1146             fail("Exception should be thrown immediately.");
1147         } catch (NullPointerException e) {
1148             // pass
1149         }
1150     }
1151 
1152     @Test
testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()1153     public void testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()
1154             throws Exception {
1155         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID);
1156         final NotificationChannel channel =
1157                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1158         mBinderService.createNotificationChannels(PKG_NO_CHANNELS,
1159                 new ParceledListSlice(Arrays.asList(channel)));
1160         verify(mWorkerHandler).post(eq(new NotificationManagerService
1161                 .ShowNotificationPermissionPromptRunnable(PKG_NO_CHANNELS,
1162                 mUserId, TEST_TASK_ID, mPermissionPolicyInternal)));
1163     }
1164 
1165     @Test
testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()1166     public void testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()
1167             throws Exception {
1168         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID);
1169         assertTrue(mBinderService.getNumNotificationChannelsForPackage(PKG, mUid, true) > 0);
1170 
1171         final NotificationChannel channel =
1172                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1173         mBinderService.createNotificationChannels(PKG,
1174                 new ParceledListSlice(Arrays.asList(channel)));
1175         verify(mWorkerHandler, never()).post(any(
1176                 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class));
1177     }
1178 
1179     @Test
testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()1180     public void testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()
1181             throws Exception {
1182         reset(mPermissionPolicyInternal);
1183         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID);
1184 
1185         final NotificationChannel channel =
1186                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1187         mBinderService.createNotificationChannels(PKG,
1188                 new ParceledListSlice(Arrays.asList(channel)));
1189 
1190         verify(mWorkerHandler, never()).post(any(
1191                 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class));
1192     }
1193 
1194     @Test
testCreateNotificationChannels_TwoChannels()1195     public void testCreateNotificationChannels_TwoChannels() throws Exception {
1196         final NotificationChannel channel1 =
1197                 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
1198         final NotificationChannel channel2 =
1199                 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
1200         mBinderService.createNotificationChannels(PKG,
1201                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
1202         assertTrue(mBinderService.getNotificationChannel(
1203                 PKG, mContext.getUserId(), PKG, "id1") != null);
1204         assertTrue(mBinderService.getNotificationChannel(
1205                 PKG, mContext.getUserId(), PKG, "id2") != null);
1206     }
1207 
1208     @Test
testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()1209     public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
1210             throws Exception {
1211         final NotificationChannel channel =
1212                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1213         mBinderService.createNotificationChannels(PKG,
1214                 new ParceledListSlice(Arrays.asList(channel)));
1215 
1216         // Recreating the channel doesn't throw, but ignores importance.
1217         final NotificationChannel dupeChannel =
1218                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
1219         mBinderService.createNotificationChannels(PKG,
1220                 new ParceledListSlice(Arrays.asList(dupeChannel)));
1221         final NotificationChannel createdChannel =
1222                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1223         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
1224     }
1225 
1226     @Test
testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()1227     public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
1228             throws Exception {
1229         final NotificationChannel channel =
1230                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1231         mBinderService.createNotificationChannels(PKG,
1232                 new ParceledListSlice(Arrays.asList(channel)));
1233 
1234         // Recreating with a lower importance is allowed to modify the channel.
1235         final NotificationChannel dupeChannel =
1236                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
1237         mBinderService.createNotificationChannels(PKG,
1238                 new ParceledListSlice(Arrays.asList(dupeChannel)));
1239         final NotificationChannel createdChannel =
1240                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1241         assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
1242     }
1243 
1244     @Test
testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()1245     public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
1246             throws Exception {
1247         final NotificationChannel channel =
1248                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1249         mBinderService.createNotificationChannels(PKG,
1250                 new ParceledListSlice(Arrays.asList(channel)));
1251 
1252         // The user modifies importance directly, can no longer be changed by the app.
1253         final NotificationChannel updatedChannel =
1254                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
1255         mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
1256 
1257         // Recreating with a lower importance leaves channel unchanged.
1258         final NotificationChannel dupeChannel =
1259                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
1260         mBinderService.createNotificationChannels(PKG,
1261                 new ParceledListSlice(Arrays.asList(dupeChannel)));
1262         final NotificationChannel createdChannel =
1263                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1264         assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
1265     }
1266 
1267     @Test
testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()1268     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
1269             throws Exception {
1270         final NotificationChannel channel1 =
1271                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1272         final NotificationChannel channel2 =
1273                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
1274         mBinderService.createNotificationChannels(PKG,
1275                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
1276         final NotificationChannel createdChannel =
1277                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1278         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
1279     }
1280 
1281     @Test
testBlockedNotifications_suspended()1282     public void testBlockedNotifications_suspended() throws Exception {
1283         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
1284 
1285         NotificationChannel channel = new NotificationChannel("id", "name",
1286                 IMPORTANCE_HIGH);
1287         NotificationRecord r = generateNotificationRecord(channel);
1288 
1289         // isBlocked is only used for user blocking, not app suspension
1290         assertFalse(mService.isRecordBlockedLocked(r));
1291     }
1292 
1293     @Test
testBlockedNotifications_blockedChannel()1294     public void testBlockedNotifications_blockedChannel() throws Exception {
1295         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1296 
1297         NotificationChannel channel = new NotificationChannel("id", "name",
1298                 NotificationManager.IMPORTANCE_NONE);
1299         NotificationRecord r = generateNotificationRecord(channel);
1300         assertTrue(mService.isRecordBlockedLocked(r));
1301 
1302         mBinderService.createNotificationChannels(
1303                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1304         final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1305         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1306                 "testBlockedNotifications_blockedChannel",
1307                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1308         waitForIdle();
1309         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1310     }
1311 
1312     @Test
testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()1313     public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
1314             throws Exception {
1315         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1316         when(mAmi.applyForegroundServiceNotification(
1317                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1318 
1319         NotificationChannel channel = new NotificationChannel("blocked", "name",
1320                 NotificationManager.IMPORTANCE_NONE);
1321         mBinderService.createNotificationChannels(
1322                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1323 
1324         final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1325         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1326         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1327                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1328         waitForIdle();
1329         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1330         assertEquals(IMPORTANCE_LOW,
1331                 mService.getNotificationRecord(sbn.getKey()).getImportance());
1332         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1333                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1334     }
1335 
1336     @Test
testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()1337     public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
1338             throws Exception {
1339         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1340         when(mAmi.applyForegroundServiceNotification(
1341                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1342 
1343         NotificationChannel channel =
1344                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
1345         mBinderService.createNotificationChannels(
1346                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1347 
1348         NotificationChannel update =
1349                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1350         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1351         waitForIdle();
1352         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1353                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1354 
1355         StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1356         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1357         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1358                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1359         waitForIdle();
1360         // The first time a foreground service notification is shown, we allow the channel
1361         // to be updated to allow it to be seen.
1362         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1363         assertEquals(IMPORTANCE_LOW,
1364                 mService.getNotificationRecord(sbn.getKey()).getImportance());
1365         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1366                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1367         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1368         waitForIdle();
1369 
1370         update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1371         update.setUserVisibleTaskShown(true);
1372         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1373         waitForIdle();
1374         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1375                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1376 
1377         sbn = generateNotificationRecord(channel).getSbn();
1378         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1379         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1380                 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
1381                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1382         waitForIdle();
1383         // The second time it is shown, we keep the user's preference.
1384         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1385         assertNull(mService.getNotificationRecord(sbn.getKey()));
1386         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1387                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1388     }
1389 
1390     @Test
testBlockedNotifications_blockedChannelGroup()1391     public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1392         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1393         mService.setPreferencesHelper(mPreferencesHelper);
1394         when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1395                 thenReturn(true);
1396 
1397         NotificationChannel channel = new NotificationChannel("id", "name",
1398                 NotificationManager.IMPORTANCE_HIGH);
1399         channel.setGroup("something");
1400         NotificationRecord r = generateNotificationRecord(channel);
1401         assertTrue(mService.isRecordBlockedLocked(r));
1402     }
1403 
1404     @Test
testEnqueuedBlockedNotifications_blockedApp()1405     public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
1406         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1407         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1408 
1409         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1410         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1411                 "testEnqueuedBlockedNotifications_blockedApp",
1412                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1413         waitForIdle();
1414         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1415     }
1416 
1417     @Test
testEnqueuedBlockedNotifications_blockedAppForegroundService()1418     public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1419         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1420         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1421         when(mAmi.applyForegroundServiceNotification(
1422                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1423 
1424         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1425         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1426         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1427                 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
1428                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1429         waitForIdle();
1430         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1431         assertNull(mService.getNotificationRecord(sbn.getKey()));
1432     }
1433 
1434     /**
1435      * Confirm an application with the SEND_CATEGORY_CAR_NOTIFICATIONS permission on automotive
1436      * devices can use car categories.
1437      */
1438     @Test
testEnqueuedRestrictedNotifications_hasPermission()1439     public void testEnqueuedRestrictedNotifications_hasPermission() throws Exception {
1440         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1441                 .thenReturn(true);
1442         // SEND_CATEGORY_CAR_NOTIFICATIONS is a system-level permission that this test cannot
1443         // obtain. Mocking out enforce permission call to ensure notifications can be created when
1444         // permitted.
1445         doNothing().when(mContext).enforceCallingPermission(
1446                 eq("android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"), anyString());
1447         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1448                 Notification.CATEGORY_CAR_WARNING,
1449                 Notification.CATEGORY_CAR_INFORMATION);
1450         int id = 0;
1451         for (String category: categories) {
1452             final StatusBarNotification sbn =
1453                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
1454             sbn.getNotification().category = category;
1455             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1456                     "testEnqueuedRestrictedNotifications_asSystem",
1457                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1458         }
1459         waitForIdle();
1460         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1461     }
1462 
1463 
1464     /**
1465      * Confirm restricted notification categories only apply to automotive.
1466      */
1467     @Test
testEnqueuedRestrictedNotifications_notAutomotive()1468     public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1469         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1470                 .thenReturn(false);
1471         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1472                 Notification.CATEGORY_CAR_WARNING,
1473                 Notification.CATEGORY_CAR_INFORMATION);
1474         int id = 0;
1475         for (String category: categories) {
1476             final StatusBarNotification sbn =
1477                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
1478             sbn.getNotification().category = category;
1479             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1480                     "testEnqueuedRestrictedNotifications_notAutomotive",
1481                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1482         }
1483         waitForIdle();
1484         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1485     }
1486 
1487     /**
1488      * Confirm if an application tries to use the car categories on a automotive device without the
1489      * SEND_CATEGORY_CAR_NOTIFICATIONS permission that a security exception will be thrown.
1490      */
1491     @Test
testEnqueuedRestrictedNotifications_noPermission()1492     public void testEnqueuedRestrictedNotifications_noPermission() throws Exception {
1493         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1494                 .thenReturn(true);
1495         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1496                 Notification.CATEGORY_CAR_WARNING,
1497                 Notification.CATEGORY_CAR_INFORMATION);
1498         for (String category: categories) {
1499             final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1500             sbn.getNotification().category = category;
1501             try {
1502                 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1503                         "testEnqueuedRestrictedNotifications_badUser",
1504                         sbn.getId(), sbn.getNotification(), sbn.getUserId());
1505                 fail("Calls from non system apps should not allow use of restricted categories");
1506             } catch (SecurityException e) {
1507                 // pass
1508             }
1509         }
1510         waitForIdle();
1511         assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1512     }
1513 
1514     @Test
testSetNotificationsEnabledForPackage_noChange()1515     public void testSetNotificationsEnabledForPackage_noChange() throws Exception {
1516         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
1517         mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, true);
1518 
1519         verify(mPermissionHelper, never()).setNotificationPermission(
1520                 anyString(), anyInt(), anyBoolean(), anyBoolean());
1521     }
1522 
1523     @Test
testSetNotificationsEnabledForPackage()1524     public void testSetNotificationsEnabledForPackage() throws Exception {
1525         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
1526         mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, false);
1527 
1528         verify(mPermissionHelper).setNotificationPermission(
1529                 mContext.getPackageName(), mUserId, false, true);
1530 
1531         verify(mAppOpsManager, never()).setMode(anyInt(), anyInt(), anyString(), anyInt());
1532         List<NotificationChannelLoggerFake.CallRecord> calls = mLogger.getCalls();
1533         Assert.assertEquals(
1534                 NotificationChannelLogger.NotificationChannelEvent.APP_NOTIFICATIONS_BLOCKED,
1535                 calls.get(calls.size() -1).event);
1536     }
1537 
1538     @Test
testBlockedNotifications_blockedByAssistant()1539     public void testBlockedNotifications_blockedByAssistant() throws Exception {
1540         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1541         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
1542 
1543         NotificationChannel channel = new NotificationChannel("id", "name",
1544                 NotificationManager.IMPORTANCE_HIGH);
1545         NotificationRecord r = generateNotificationRecord(channel);
1546         mService.addEnqueuedNotification(r);
1547 
1548         Bundle bundle = new Bundle();
1549         bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
1550         Adjustment adjustment = new Adjustment(
1551                 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
1552         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
1553 
1554         NotificationManagerService.PostNotificationRunnable runnable =
1555                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
1556                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
1557         runnable.run();
1558         waitForIdle();
1559 
1560         verify(mUsageStats, never()).registerPostedByApp(any());
1561     }
1562 
1563     @Test
testBlockedNotifications_blockedByUser()1564     public void testBlockedNotifications_blockedByUser() throws Exception {
1565         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1566         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
1567 
1568         NotificationChannel channel = new NotificationChannel("id", "name",
1569                 NotificationManager.IMPORTANCE_HIGH);
1570         NotificationRecord r = generateNotificationRecord(channel);
1571         mService.addEnqueuedNotification(r);
1572 
1573         when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false);
1574 
1575         NotificationManagerService.PostNotificationRunnable runnable =
1576                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
1577                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
1578         runnable.run();
1579         waitForIdle();
1580 
1581         verify(mUsageStats).registerBlocked(any());
1582         verify(mUsageStats, never()).registerPostedByApp(any());
1583     }
1584 
1585     @Test
testEnqueueNotificationInternal_noChannel()1586     public void testEnqueueNotificationInternal_noChannel() throws Exception {
1587         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1588         NotificationRecord nr = generateNotificationRecord(
1589                 new NotificationChannel("did not create", "", IMPORTANCE_DEFAULT));
1590 
1591         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
1592                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
1593         waitForIdle();
1594 
1595         verify(mPermissionHelper).hasPermission(mUid);
1596         verify(mPermissionHelper, never()).hasPermission(Process.SYSTEM_UID);
1597 
1598         reset(mPermissionHelper);
1599         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
1600 
1601         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
1602                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
1603         waitForIdle();
1604 
1605         verify(mPermissionHelper).hasPermission(mUid);
1606         assertThat(mService.mChannelToastsSent).contains(mUid);
1607     }
1608 
1609     @Test
testEnqueueNotification_appBlocked()1610     public void testEnqueueNotification_appBlocked() throws Exception {
1611         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1612 
1613         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1614                 "testEnqueueNotification_appBlocked", 0,
1615                 generateNotificationRecord(null).getNotification(), 0);
1616         waitForIdle();
1617         verify(mWorkerHandler, never()).post(
1618                 any(NotificationManagerService.EnqueueNotificationRunnable.class));
1619     }
1620 
1621     @Test
testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()1622     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
1623         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1624                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1625                 generateNotificationRecord(null).getNotification(), 0);
1626         waitForIdle();
1627         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
1628         assertEquals(1, notifs.length);
1629         assertEquals(1, mService.getNotificationRecordCount());
1630     }
1631 
1632     @Test
testEnqueueNotificationWithTag_WritesExpectedLogs()1633     public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
1634         final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1635         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1636                 generateNotificationRecord(null).getNotification(), 0);
1637         waitForIdle();
1638         assertEquals(1, mNotificationRecordLogger.numCalls());
1639 
1640         NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
1641         assertTrue(call.wasLogged);
1642         assertEquals(NOTIFICATION_POSTED, call.event);
1643         assertNotNull(call.r);
1644         assertNull(call.old);
1645         assertEquals(0, call.position);
1646         assertEquals(0, call.buzzBeepBlink);
1647         assertEquals(PKG, call.r.getSbn().getPackageName());
1648         assertEquals(0, call.r.getSbn().getId());
1649         assertEquals(tag, call.r.getSbn().getTag());
1650         assertEquals(1, call.getInstanceId());  // Fake instance IDs are assigned in order
1651         assertThat(call.postDurationMillisLogged).isGreaterThan(0);
1652     }
1653 
1654     @Test
testEnqueueNotificationWithTag_LogsOnMajorUpdates()1655     public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1656         final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1657         Notification original = new Notification.Builder(mContext,
1658                 mTestNotificationChannel.getId())
1659                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1660         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1661         Notification update = new Notification.Builder(mContext,
1662                 mTestNotificationChannel.getId())
1663                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1664                 .setCategory(Notification.CATEGORY_ALARM).build();
1665         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1666         waitForIdle();
1667         assertEquals(2, mNotificationRecordLogger.numCalls());
1668 
1669         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1670         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1671         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
1672         assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0);
1673 
1674         assertTrue(mNotificationRecordLogger.get(1).wasLogged);
1675         assertEquals(NOTIFICATION_UPDATED, mNotificationRecordLogger.event(1));
1676         // Instance ID doesn't change on update of an active notification
1677         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
1678         assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isGreaterThan(0);
1679     }
1680 
1681     @Test
testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate()1682     public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1683         final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
1684         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1685                 generateNotificationRecord(null).getNotification(), 0);
1686         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1687                 generateNotificationRecord(null).getNotification(), 0);
1688         waitForIdle();
1689         assertEquals(2, mNotificationRecordLogger.numCalls());
1690         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1691         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1692         assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1693         assertNull(mNotificationRecordLogger.event(1));
1694     }
1695 
1696     @Test
testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate()1697     public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1698         final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1699         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1700                 generateNotificationRecord(null).getNotification(),
1701                 0);
1702         final Notification notif = generateNotificationRecord(null).getNotification();
1703         notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1704         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1705         waitForIdle();
1706         assertEquals(2, mNotificationRecordLogger.numCalls());
1707         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1708         assertNull(mNotificationRecordLogger.event(1));
1709     }
1710 
1711     @Test
testEnqueueNotificationWithTag_LogsAgainAfterCancel()1712     public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1713         final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1714         Notification notification = new Notification.Builder(mContext,
1715                 mTestNotificationChannel.getId())
1716                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1717         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1718         waitForIdle();
1719         mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1720         waitForIdle();
1721         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1722         waitForIdle();
1723         assertEquals(3, mNotificationRecordLogger.numCalls());
1724 
1725         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1726         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1727         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
1728         assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0);
1729 
1730         assertEquals(
1731                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
1732                 mNotificationRecordLogger.event(1));
1733         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
1734         // Cancel is not post, so no logged post_duration_millis.
1735         assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isNull();
1736 
1737         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(2));
1738         assertTrue(mNotificationRecordLogger.get(2).wasLogged);
1739         // New instance ID because notification was canceled before re-post
1740         assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
1741         assertThat(mNotificationRecordLogger.get(2).postDurationMillisLogged).isGreaterThan(0);
1742     }
1743 
1744     @Test
testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed()1745     public void testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed() throws Exception {
1746         when(mAmi.applyForegroundServiceNotification(
1747                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1748         mContext.getTestablePermissions().setPermission(
1749                 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED);
1750 
1751         final String tag = "testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed";
1752 
1753         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1754                 .setContentTitle("foo")
1755                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1756                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
1757                 .build();
1758         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, tag, mUid, 0,
1759                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
1760         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag,
1761                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1762         waitForIdle();
1763 
1764         StatusBarNotification[] notifs =
1765                 mBinderService.getActiveNotifications(PKG);
1766         assertThat(notifs[0].getNotification().flags).isEqualTo(
1767                 FLAG_FOREGROUND_SERVICE | FLAG_CAN_COLORIZE | FLAG_NO_CLEAR);
1768     }
1769 
1770     @Test
testEnqueueNotificationWithTag_nullAction_fixed()1771     public void testEnqueueNotificationWithTag_nullAction_fixed() throws Exception {
1772         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1773                 .setContentTitle("foo")
1774                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1775                 .addAction(new Notification.Action.Builder(null, "one", null).build())
1776                 .addAction(new Notification.Action.Builder(null, "two", null).build())
1777                 .addAction(new Notification.Action.Builder(null, "three", null).build())
1778                 .build();
1779         n.actions[1] = null;
1780 
1781         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0);
1782         waitForIdle();
1783 
1784         StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG);
1785         assertThat(posted).hasLength(1);
1786         assertThat(posted[0].getNotification().actions).hasLength(2);
1787         assertThat(posted[0].getNotification().actions[0].title.toString()).isEqualTo("one");
1788         assertThat(posted[0].getNotification().actions[1].title.toString()).isEqualTo("three");
1789     }
1790 
1791     @Test
testEnqueueNotificationWithTag_allNullActions_fixed()1792     public void testEnqueueNotificationWithTag_allNullActions_fixed() throws Exception {
1793         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1794                 .setContentTitle("foo")
1795                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1796                 .addAction(new Notification.Action.Builder(null, "one", null).build())
1797                 .addAction(new Notification.Action.Builder(null, "two", null).build())
1798                 .build();
1799         n.actions[0] = null;
1800         n.actions[1] = null;
1801 
1802         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0);
1803         waitForIdle();
1804 
1805         StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG);
1806         assertThat(posted).hasLength(1);
1807         assertThat(posted[0].getNotification().actions).isNull();
1808     }
1809 
1810     @Test
enqueueNotificationWithTag_usesAndFinishesTracker()1811     public void enqueueNotificationWithTag_usesAndFinishesTracker() throws Exception {
1812         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1813                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1814                 generateNotificationRecord(null).getNotification(), 0);
1815 
1816         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1817         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isTrue();
1818 
1819         waitForIdle();
1820 
1821         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(1);
1822         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1823         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1824     }
1825 
1826     @Test
enqueueNotificationWithTag_throws_usesAndCancelsTracker()1827     public void enqueueNotificationWithTag_throws_usesAndCancelsTracker() throws Exception {
1828         // Simulate not enqueued due to rejected inputs.
1829         assertThrows(Exception.class,
1830                 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG,
1831                         "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1832                         /* notification= */ null, 0));
1833 
1834         waitForIdle();
1835 
1836         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0);
1837         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1838         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1839     }
1840 
1841     @Test
enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker()1842     public void enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker() throws Exception {
1843         // Simulate not enqueued due to snoozing inputs.
1844         when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any()))
1845                 .thenReturn("zzzzzzz");
1846 
1847         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1848                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1849                 generateNotificationRecord(null).getNotification(), 0);
1850         waitForIdle();
1851 
1852         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0);
1853         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1854         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1855     }
1856 
1857     @Test
enqueueNotificationWithTag_notPosted_usesAndCancelsTracker()1858     public void enqueueNotificationWithTag_notPosted_usesAndCancelsTracker() throws Exception {
1859         // Simulate not posted due to blocked app.
1860         when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false);
1861 
1862         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1863                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1864                 generateNotificationRecord(null).getNotification(), 0);
1865         waitForIdle();
1866 
1867         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0);
1868         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1869         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1870     }
1871 
1872     @Test
enqueueNotification_acquiresAndReleasesWakeLock()1873     public void enqueueNotification_acquiresAndReleasesWakeLock() throws Exception {
1874         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1875                 "enqueueNotification_acquiresAndReleasesWakeLock", 0,
1876                 generateNotificationRecord(null).getNotification(), 0);
1877 
1878         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1879         assertThat(mAcquiredWakeLocks).hasSize(1);
1880         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
1881 
1882         waitForIdle();
1883 
1884         assertThat(mAcquiredWakeLocks).hasSize(1);
1885         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1886     }
1887 
1888     @Test
enqueueNotification_throws_acquiresAndReleasesWakeLock()1889     public void enqueueNotification_throws_acquiresAndReleasesWakeLock() throws Exception {
1890         // Simulate not enqueued due to rejected inputs.
1891         assertThrows(Exception.class,
1892                 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG,
1893                         "enqueueNotification_throws_acquiresAndReleasesWakeLock", 0,
1894                         /* notification= */ null, 0));
1895 
1896         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1897         assertThat(mAcquiredWakeLocks).hasSize(1);
1898         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1899     }
1900 
1901     @Test
enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock()1902     public void enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock() throws Exception {
1903         // Simulate not enqueued due to snoozing inputs.
1904         when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any()))
1905                 .thenReturn("zzzzzzz");
1906 
1907         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1908                 "enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock", 0,
1909                 generateNotificationRecord(null).getNotification(), 0);
1910 
1911         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1912         assertThat(mAcquiredWakeLocks).hasSize(1);
1913         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
1914 
1915         waitForIdle();
1916 
1917         assertThat(mAcquiredWakeLocks).hasSize(1);
1918         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1919     }
1920 
1921     @Test
enqueueNotification_notPosted_acquiresAndReleasesWakeLock()1922     public void enqueueNotification_notPosted_acquiresAndReleasesWakeLock() throws Exception {
1923         // Simulate enqueued but not posted due to missing small icon.
1924         Notification notif = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1925                 .setContentTitle("foo")
1926                 .build();
1927 
1928         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1929                 "enqueueNotification_notPosted_acquiresAndReleasesWakeLock", 0,
1930                 notif, 0);
1931 
1932         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1933         assertThat(mAcquiredWakeLocks).hasSize(1);
1934         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
1935 
1936         waitForIdle();
1937 
1938         // NLSes were not called.
1939         verify(mListeners, never()).prepareNotifyPostedLocked(any(), any(), anyBoolean());
1940 
1941         assertThat(mAcquiredWakeLocks).hasSize(1);
1942         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1943     }
1944 
1945     @Test
enqueueNotification_setsWakeLockWorkSource()1946     public void enqueueNotification_setsWakeLockWorkSource() throws Exception {
1947         // Use a "full" mock for the PowerManager (instead of the one that delegates to the real
1948         // service) so we can return a mocked WakeLock that we can verify() on.
1949         reset(mPowerManager);
1950         WakeLock wakeLock = mock(WakeLock.class);
1951         when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(wakeLock);
1952 
1953         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1954                 "enqueueNotification_setsWakeLockWorkSource", 0,
1955                 generateNotificationRecord(null).getNotification(), 0);
1956         waitForIdle();
1957 
1958         InOrder inOrder = inOrder(mPowerManager, wakeLock);
1959         inOrder.verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1960         inOrder.verify(wakeLock).setWorkSource(eq(new WorkSource(mUid, PKG)));
1961         inOrder.verify(wakeLock).acquire(anyLong());
1962         inOrder.verify(wakeLock).release();
1963         inOrder.verifyNoMoreInteractions();
1964     }
1965 
1966     @Test
enqueueNotification_wakeLockSystemPropertyOff_noWakeLock()1967     public void enqueueNotification_wakeLockSystemPropertyOff_noWakeLock() throws Exception {
1968         mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, false);
1969         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
1970                 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false);
1971 
1972         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1973                 "enqueueNotification_setsWakeLockWorkSource", 0,
1974                 generateNotificationRecord(null).getNotification(), 0);
1975         waitForIdle();
1976 
1977         verifyZeroInteractions(mPowerManager);
1978     }
1979 
1980     @Test
enqueueNotification_wakeLockDeviceConfigOff_noWakeLock()1981     public void enqueueNotification_wakeLockDeviceConfigOff_noWakeLock() throws Exception {
1982         mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
1983         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
1984                 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "false", false);
1985 
1986         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1987                 "enqueueNotification_setsWakeLockWorkSource", 0,
1988                 generateNotificationRecord(null).getNotification(), 0);
1989         waitForIdle();
1990 
1991         verifyZeroInteractions(mPowerManager);
1992     }
1993 
1994     @Test
testCancelNonexistentNotification()1995     public void testCancelNonexistentNotification() throws Exception {
1996         mBinderService.cancelNotificationWithTag(PKG, PKG,
1997                 "testCancelNonexistentNotification", 0, 0);
1998         waitForIdle();
1999         // The notification record logger doesn't even get called when a nonexistent notification
2000         // is cancelled, because that happens very frequently and is not interesting.
2001         assertEquals(0, mNotificationRecordLogger.numCalls());
2002     }
2003 
2004     @Test
testCancelNotificationImmediatelyAfterEnqueue()2005     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
2006         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2007                 "testCancelNotificationImmediatelyAfterEnqueue", 0,
2008                 generateNotificationRecord(null).getNotification(), 0);
2009         mBinderService.cancelNotificationWithTag(PKG, PKG,
2010                 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
2011         waitForIdle();
2012         StatusBarNotification[] notifs =
2013                 mBinderService.getActiveNotifications(PKG);
2014         assertEquals(0, notifs.length);
2015         assertEquals(0, mService.getNotificationRecordCount());
2016     }
2017 
2018     @Test
testPostCancelPostNotifiesListeners()2019     public void testPostCancelPostNotifiesListeners() throws Exception {
2020         // WHEN a notification is posted
2021         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2022         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
2023                 sbn.getNotification(), sbn.getUserId());
2024         mTestableLooper.moveTimeForward(1);
2025         // THEN it is canceled
2026         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
2027         mTestableLooper.moveTimeForward(1);
2028         // THEN it is posted again (before the cancel has a chance to finish)
2029         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
2030                 sbn.getNotification(), sbn.getUserId());
2031         // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
2032         waitForIdle();
2033 
2034         // The final enqueue made it to the listener instead of being canceled
2035         StatusBarNotification[] notifs =
2036                 mBinderService.getActiveNotifications(PKG);
2037         assertEquals(1, notifs.length);
2038         assertEquals(1, mService.getNotificationRecordCount());
2039     }
2040 
2041     @Test
testCancelNotificationWhilePostedAndEnqueued()2042     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
2043         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2044                 "testCancelNotificationWhilePostedAndEnqueued", 0,
2045                 generateNotificationRecord(null).getNotification(), 0);
2046         waitForIdle();
2047         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2048                 "testCancelNotificationWhilePostedAndEnqueued", 0,
2049                 generateNotificationRecord(null).getNotification(), 0);
2050         mBinderService.cancelNotificationWithTag(PKG, PKG,
2051                 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
2052         waitForIdle();
2053         StatusBarNotification[] notifs =
2054                 mBinderService.getActiveNotifications(PKG);
2055         assertEquals(0, notifs.length);
2056         assertEquals(0, mService.getNotificationRecordCount());
2057         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
2058         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
2059         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
2060     }
2061 
2062     @Test
testCancelNotificationsFromListenerImmediatelyAfterEnqueue()2063     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
2064         NotificationRecord r = generateNotificationRecord(null);
2065         final StatusBarNotification sbn = r.getSbn();
2066         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2067                 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
2068                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2069         mBinderService.cancelNotificationsFromListener(null, null);
2070         waitForIdle();
2071         StatusBarNotification[] notifs =
2072                 mBinderService.getActiveNotifications(sbn.getPackageName());
2073         assertEquals(0, notifs.length);
2074         assertEquals(0, mService.getNotificationRecordCount());
2075     }
2076 
2077     @Test
testCancelAllNotificationsImmediatelyAfterEnqueue()2078     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
2079         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2080         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2081                 "testCancelAllNotificationsImmediatelyAfterEnqueue",
2082                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2083         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2084         waitForIdle();
2085         StatusBarNotification[] notifs =
2086                 mBinderService.getActiveNotifications(sbn.getPackageName());
2087         assertEquals(0, notifs.length);
2088         assertEquals(0, mService.getNotificationRecordCount());
2089     }
2090 
2091     @Test
testUserInitiatedClearAll_noLeak()2092     public void testUserInitiatedClearAll_noLeak() throws Exception {
2093         final NotificationRecord n = generateNotificationRecord(
2094                 mTestNotificationChannel, 1, "group", true);
2095 
2096         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2097                 "testUserInitiatedClearAll_noLeak",
2098                 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
2099         waitForIdle();
2100 
2101         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2102                 n.getUserId());
2103         waitForIdle();
2104         StatusBarNotification[] notifs =
2105                 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
2106         assertEquals(0, notifs.length);
2107         assertEquals(0, mService.getNotificationRecordCount());
2108         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
2109         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
2110         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
2111     }
2112 
2113     @Test
testCancelAllNotificationsCancelsChildren()2114     public void testCancelAllNotificationsCancelsChildren() throws Exception {
2115         final NotificationRecord parent = generateNotificationRecord(
2116                 mTestNotificationChannel, 1, "group1", true);
2117         final NotificationRecord child = generateNotificationRecord(
2118                 mTestNotificationChannel, 2, "group1", false);
2119 
2120         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2121                 "testCancelAllNotificationsCancelsChildren",
2122                 parent.getSbn().getId(), parent.getSbn().getNotification(),
2123                 parent.getSbn().getUserId());
2124         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2125                 "testCancelAllNotificationsCancelsChildren",
2126                 child.getSbn().getId(), child.getSbn().getNotification(),
2127                 child.getSbn().getUserId());
2128         waitForIdle();
2129 
2130         mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
2131         waitForIdle();
2132         assertEquals(0, mService.getNotificationRecordCount());
2133     }
2134 
2135     @Test
testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()2136     public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
2137         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2138         for (int i = 0; i < 10; i++) {
2139             mBinderService.enqueueNotificationWithTag(PKG, PKG,
2140                     "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
2141                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
2142         }
2143         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2144         waitForIdle();
2145 
2146         assertEquals(0, mService.getNotificationRecordCount());
2147     }
2148 
2149     @Test
testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()2150     public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
2151         final NotificationRecord parent = generateNotificationRecord(
2152                 mTestNotificationChannel, 1, "group1", true);
2153         final NotificationRecord parentAsChild = generateNotificationRecord(
2154                 mTestNotificationChannel, 1, "group1", false);
2155         final NotificationRecord child = generateNotificationRecord(
2156                 mTestNotificationChannel, 2, "group1", false);
2157 
2158         // fully post parent notification
2159         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2160                 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
2161                 parent.getSbn().getId(), parent.getSbn().getNotification(),
2162                 parent.getSbn().getUserId());
2163         waitForIdle();
2164 
2165         // enqueue the child several times
2166         for (int i = 0; i < 10; i++) {
2167             mBinderService.enqueueNotificationWithTag(PKG, PKG,
2168                     "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
2169                     child.getSbn().getId(), child.getSbn().getNotification(),
2170                     child.getSbn().getUserId());
2171         }
2172         // make the parent a child, which will cancel the child notification
2173         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2174                 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
2175                 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
2176                 parentAsChild.getSbn().getUserId());
2177         waitForIdle();
2178 
2179         assertEquals(0, mService.getNotificationRecordCount());
2180     }
2181 
2182     @Test
testAutobundledSummary_notificationAdded()2183     public void testAutobundledSummary_notificationAdded() {
2184         NotificationRecord summary =
2185                 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
2186         summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
2187         mService.addNotification(summary);
2188         mService.mSummaryByGroupKey.put("pkg", summary);
2189         mService.mAutobundledSummaries.put(0, new ArrayMap<>());
2190         mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
2191 
2192         mService.updateAutobundledSummaryFlags(
2193                 0, "pkg", GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT, false);
2194         waitForIdle();
2195 
2196         assertTrue(summary.getSbn().isOngoing());
2197     }
2198 
2199     @Test
testAutobundledSummary_notificationRemoved()2200     public void testAutobundledSummary_notificationRemoved() {
2201         NotificationRecord summary =
2202                 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
2203         summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
2204         summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2205         mService.addNotification(summary);
2206         mService.mAutobundledSummaries.put(0, new ArrayMap<>());
2207         mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
2208         mService.mSummaryByGroupKey.put("pkg", summary);
2209 
2210         mService.updateAutobundledSummaryFlags(0, "pkg", GroupHelper.BASE_FLAGS, false);
2211         waitForIdle();
2212 
2213         assertFalse(summary.getSbn().isOngoing());
2214     }
2215 
2216     @Test
testCancelAllNotifications_IgnoreForegroundService()2217     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
2218         when(mAmi.applyForegroundServiceNotification(
2219                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
2220         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2221         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2222         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2223                 "testCancelAllNotifications_IgnoreForegroundService",
2224                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2225         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2226         waitForIdle();
2227         StatusBarNotification[] notifs =
2228                 mBinderService.getActiveNotifications(sbn.getPackageName());
2229         assertEquals(1, notifs.length);
2230         assertEquals(1, mService.getNotificationRecordCount());
2231     }
2232 
2233     @Test
testCancelAllNotifications_FgsFlag_NoFgs_Allowed()2234     public void testCancelAllNotifications_FgsFlag_NoFgs_Allowed() throws Exception {
2235         when(mAmi.applyForegroundServiceNotification(
2236                 any(), anyString(), anyInt(), anyString(), anyInt()))
2237                 .thenReturn(NOT_FOREGROUND_SERVICE);
2238         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2239         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2240         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2241                 "testCancelAllNotifications_IgnoreForegroundService",
2242                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2243         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2244         waitForIdle();
2245         StatusBarNotification[] notifs =
2246                 mBinderService.getActiveNotifications(sbn.getPackageName());
2247         assertEquals(0, notifs.length);
2248     }
2249 
2250     @Test
testCancelAllNotifications_IgnoreOtherPackages()2251     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
2252         when(mAmi.applyForegroundServiceNotification(
2253                 any(), anyString(), anyInt(), anyString(), anyInt()))
2254                 .thenReturn(SHOW_IMMEDIATELY);
2255         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2256         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2257         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2258                 "testCancelAllNotifications_IgnoreOtherPackages",
2259                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2260         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
2261         waitForIdle();
2262         StatusBarNotification[] notifs =
2263                 mBinderService.getActiveNotifications(sbn.getPackageName());
2264         assertEquals(1, notifs.length);
2265         assertEquals(1, mService.getNotificationRecordCount());
2266     }
2267 
2268     @Test
testCancelAllNotifications_NullPkgRemovesAll()2269     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
2270         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2271         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2272                 "testCancelAllNotifications_NullPkgRemovesAll",
2273                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2274         mBinderService.cancelAllNotifications(null, sbn.getUserId());
2275         waitForIdle();
2276         StatusBarNotification[] notifs =
2277                 mBinderService.getActiveNotifications(sbn.getPackageName());
2278         assertEquals(0, notifs.length);
2279         assertEquals(0, mService.getNotificationRecordCount());
2280     }
2281 
2282     @Test
testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()2283     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
2284         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2285         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2286                 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
2287                 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
2288         // Null pkg is how we signal a user switch.
2289         mBinderService.cancelAllNotifications(null, sbn.getUserId());
2290         waitForIdle();
2291         StatusBarNotification[] notifs =
2292                 mBinderService.getActiveNotifications(sbn.getPackageName());
2293         assertEquals(1, notifs.length);
2294         assertEquals(1, mService.getNotificationRecordCount());
2295     }
2296 
2297     @Test
testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()2298     public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
2299         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2300         sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2301         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2302                 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
2303                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2304         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2305         waitForIdle();
2306         StatusBarNotification[] notifs =
2307                 mBinderService.getActiveNotifications(sbn.getPackageName());
2308         assertEquals(0, notifs.length);
2309     }
2310 
2311     @Test
testCancelAllNotifications_CancelsNoClearFlag()2312     public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
2313         final NotificationRecord notif = generateNotificationRecord(
2314                 mTestNotificationChannel, 1, "group", true);
2315         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2316         mService.addNotification(notif);
2317         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0,
2318                 notif.getUserId(), REASON_CANCEL);
2319         waitForIdle();
2320         StatusBarNotification[] notifs =
2321                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2322         assertEquals(0, notifs.length);
2323     }
2324 
2325     @Test
testUserInitiatedCancelAllOnClearAll_NoClearFlag()2326     public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
2327         final NotificationRecord notif = generateNotificationRecord(
2328                 mTestNotificationChannel, 1, "group", true);
2329         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2330         mService.addNotification(notif);
2331 
2332         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2333                 notif.getUserId());
2334         waitForIdle();
2335         StatusBarNotification[] notifs =
2336                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2337         assertEquals(1, notifs.length);
2338     }
2339 
2340     @Test
testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()2341     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
2342         when(mAmi.applyForegroundServiceNotification(
2343                 any(), anyString(), anyInt(), anyString(), anyInt()))
2344                 .thenReturn(SHOW_IMMEDIATELY);
2345         Notification n =
2346                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2347                         .setSmallIcon(android.R.drawable.sym_def_app_icon)
2348                         .build();
2349         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
2350                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
2351         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2352         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2353                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2354         mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
2355                 sbn.getUserId());
2356         waitForIdle();
2357         StatusBarNotification[] notifs =
2358                 mBinderService.getActiveNotifications(sbn.getPackageName());
2359         assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
2360     }
2361 
2362     @Test
testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()2363     public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
2364         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2365         sbn.getNotification().flags =
2366                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
2367         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
2368                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2369         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
2370         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
2371                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2372         mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
2373                 sbn.getUserId());
2374         waitForIdle();
2375         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
2376         assertEquals(0, mService.getNotificationRecordCount());
2377     }
2378 
2379     @Test
testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()2380     public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()
2381             throws Exception {
2382         when(mAmi.applyForegroundServiceNotification(
2383                 any(), anyString(), anyInt(), anyString(), anyInt()))
2384                 .thenReturn(SHOW_IMMEDIATELY);
2385         mService.isSystemUid = false;
2386         mService.isSystemAppId = false;
2387         final NotificationRecord parent = generateNotificationRecord(
2388                 mTestNotificationChannel, 1, "group", true);
2389         final NotificationRecord child = generateNotificationRecord(
2390                 mTestNotificationChannel, 2, "group", false);
2391         final NotificationRecord child2 = generateNotificationRecord(
2392                 mTestNotificationChannel, 3, "group", false);
2393         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2394         mService.addNotification(parent);
2395         mService.addNotification(child);
2396         mService.addNotification(child2);
2397         mService.getBinderService().cancelNotificationWithTag(
2398                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2399                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2400         waitForIdle();
2401         StatusBarNotification[] notifs =
2402                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2403         assertEquals(1, notifs.length);
2404     }
2405 
2406     @Test
testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()2407     public void testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()
2408             throws Exception {
2409         when(mAmi.applyForegroundServiceNotification(
2410                 any(), anyString(), anyInt(), anyString(), anyInt()))
2411                 .thenReturn(SHOW_IMMEDIATELY);
2412         mService.isSystemUid = false;
2413         mService.isSystemAppId = false;
2414         final NotificationRecord parent = generateNotificationRecord(
2415                 mTestNotificationChannel, 1, "group", true);
2416         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2417         final NotificationRecord child = generateNotificationRecord(
2418                 mTestNotificationChannel, 2, "group", false);
2419         final NotificationRecord child2 = generateNotificationRecord(
2420                 mTestNotificationChannel, 3, "group", false);
2421         mService.addNotification(parent);
2422         mService.addNotification(child);
2423         mService.addNotification(child2);
2424         mService.getBinderService().cancelNotificationWithTag(
2425                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2426                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2427         waitForIdle();
2428         StatusBarNotification[] notifs =
2429                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2430         assertEquals(3, notifs.length);
2431     }
2432 
2433     @Test
testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild()2434     public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild()
2435             throws Exception {
2436         mService.isSystemUid = false;
2437         mService.isSystemAppId = false;
2438         final NotificationRecord parent = generateNotificationRecord(
2439                 mTestNotificationChannel, 1, "group", true);
2440         final NotificationRecord child = generateNotificationRecord(
2441                 mTestNotificationChannel, 2, "group", false);
2442         final NotificationRecord child2 = generateNotificationRecord(
2443                 mTestNotificationChannel, 3, "group", false);
2444         child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2445         mService.addNotification(parent);
2446         mService.addNotification(child);
2447         mService.addNotification(child2);
2448         mService.getBinderService().cancelNotificationWithTag(
2449                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2450                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2451         waitForIdle();
2452         StatusBarNotification[] notifs =
2453                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2454         assertEquals(0, notifs.length);
2455     }
2456 
2457     @Test
testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent()2458     public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent()
2459             throws Exception {
2460         mService.isSystemUid = false;
2461         mService.isSystemAppId = false;
2462         final NotificationRecord parent = generateNotificationRecord(
2463                 mTestNotificationChannel, 1, "group", true);
2464         parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2465         final NotificationRecord child = generateNotificationRecord(
2466                 mTestNotificationChannel, 2, "group", false);
2467         final NotificationRecord child2 = generateNotificationRecord(
2468                 mTestNotificationChannel, 3, "group", false);
2469         mService.addNotification(parent);
2470         mService.addNotification(child);
2471         mService.addNotification(child2);
2472         mService.getBinderService().cancelNotificationWithTag(
2473                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2474                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2475         waitForIdle();
2476         StatusBarNotification[] notifs =
2477                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2478         assertEquals(0, notifs.length);
2479     }
2480 
2481     @Test
testCancelAllNotificationsFromApp_cannotCancelFgsChild()2482     public void testCancelAllNotificationsFromApp_cannotCancelFgsChild()
2483             throws Exception {
2484         when(mAmi.applyForegroundServiceNotification(
2485                 any(), anyString(), anyInt(), anyString(), anyInt()))
2486                 .thenReturn(SHOW_IMMEDIATELY);
2487         mService.isSystemUid = false;
2488         mService.isSystemAppId = false;
2489         final NotificationRecord parent = generateNotificationRecord(
2490                 mTestNotificationChannel, 1, "group", true);
2491         final NotificationRecord child = generateNotificationRecord(
2492                 mTestNotificationChannel, 2, "group", false);
2493         final NotificationRecord child2 = generateNotificationRecord(
2494                 mTestNotificationChannel, 3, "group", false);
2495         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2496         final NotificationRecord newGroup = generateNotificationRecord(
2497                 mTestNotificationChannel, 4, "group2", false);
2498         mService.addNotification(parent);
2499         mService.addNotification(child);
2500         mService.addNotification(child2);
2501         mService.addNotification(newGroup);
2502         mService.getBinderService().cancelAllNotifications(
2503                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2504         waitForIdle();
2505         StatusBarNotification[] notifs =
2506                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2507         assertEquals(1, notifs.length);
2508     }
2509 
2510     @Test
testCancelAllNotifications_fromApp_cannotCancelFgsParent()2511     public void testCancelAllNotifications_fromApp_cannotCancelFgsParent()
2512             throws Exception {
2513         when(mAmi.applyForegroundServiceNotification(
2514                 any(), anyString(), anyInt(), anyString(), anyInt()))
2515                 .thenReturn(SHOW_IMMEDIATELY);
2516         mService.isSystemUid = false;
2517         mService.isSystemAppId = false;
2518         final NotificationRecord parent = generateNotificationRecord(
2519                 mTestNotificationChannel, 1, "group", true);
2520         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2521         final NotificationRecord child = generateNotificationRecord(
2522                 mTestNotificationChannel, 2, "group", false);
2523         final NotificationRecord child2 = generateNotificationRecord(
2524                 mTestNotificationChannel, 3, "group", false);
2525         final NotificationRecord newGroup = generateNotificationRecord(
2526                 mTestNotificationChannel, 4, "group2", false);
2527         mService.addNotification(parent);
2528         mService.addNotification(child);
2529         mService.addNotification(child2);
2530         mService.addNotification(newGroup);
2531         mService.getBinderService().cancelAllNotifications(
2532                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2533         waitForIdle();
2534         StatusBarNotification[] notifs =
2535                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2536         assertEquals(1, notifs.length);
2537     }
2538 
2539     @Test
testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild()2540     public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild()
2541             throws Exception {
2542         mService.isSystemUid = false;
2543         mService.isSystemAppId = false;
2544         final NotificationRecord parent = generateNotificationRecord(
2545                 mTestNotificationChannel, 1, "group", true);
2546         final NotificationRecord child = generateNotificationRecord(
2547                 mTestNotificationChannel, 2, "group", false);
2548         final NotificationRecord child2 = generateNotificationRecord(
2549                 mTestNotificationChannel, 3, "group", false);
2550         child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2551         final NotificationRecord newGroup = generateNotificationRecord(
2552                 mTestNotificationChannel, 4, "group2", false);
2553         mService.addNotification(parent);
2554         mService.addNotification(child);
2555         mService.addNotification(child2);
2556         mService.addNotification(newGroup);
2557         mService.getBinderService().cancelAllNotifications(
2558                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2559         waitForIdle();
2560         StatusBarNotification[] notifs =
2561                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2562         assertEquals(0, notifs.length);
2563     }
2564 
2565     @Test
testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent()2566     public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent()
2567             throws Exception {
2568         mService.isSystemUid = false;
2569         mService.isSystemAppId = false;
2570         final NotificationRecord parent = generateNotificationRecord(
2571                 mTestNotificationChannel, 1, "group", true);
2572         parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2573         final NotificationRecord child = generateNotificationRecord(
2574                 mTestNotificationChannel, 2, "group", false);
2575         final NotificationRecord child2 = generateNotificationRecord(
2576                 mTestNotificationChannel, 3, "group", false);
2577         final NotificationRecord newGroup = generateNotificationRecord(
2578                 mTestNotificationChannel, 4, "group2", false);
2579         mService.addNotification(parent);
2580         mService.addNotification(child);
2581         mService.addNotification(child2);
2582         mService.addNotification(newGroup);
2583         mService.getBinderService().cancelAllNotifications(
2584                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2585         waitForIdle();
2586         StatusBarNotification[] notifs =
2587                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2588         assertEquals(0, notifs.length);
2589     }
2590 
2591     @Test
testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent()2592     public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent()
2593             throws Exception {
2594         final NotificationRecord parent = generateNotificationRecord(
2595                 mTestNotificationChannel, 1, "group", true);
2596         parent.getNotification().flags |= FLAG_ONGOING_EVENT;
2597         final NotificationRecord child = generateNotificationRecord(
2598                 mTestNotificationChannel, 2, "group", false);
2599         final NotificationRecord child2 = generateNotificationRecord(
2600                 mTestNotificationChannel, 3, "group", false);
2601         final NotificationRecord newGroup = generateNotificationRecord(
2602                 mTestNotificationChannel, 4, "group2", false);
2603         mService.addNotification(parent);
2604         mService.addNotification(child);
2605         mService.addNotification(child2);
2606         mService.addNotification(newGroup);
2607         mService.getBinderService().cancelNotificationsFromListener(null, null);
2608         waitForIdle();
2609         StatusBarNotification[] notifs =
2610                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2611         assertEquals(1, notifs.length);
2612     }
2613 
2614     @Test
testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild()2615     public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild()
2616             throws Exception {
2617         final NotificationRecord parent = generateNotificationRecord(
2618                 mTestNotificationChannel, 1, "group", true);
2619         final NotificationRecord child = generateNotificationRecord(
2620                 mTestNotificationChannel, 2, "group", false);
2621         final NotificationRecord child2 = generateNotificationRecord(
2622                 mTestNotificationChannel, 3, "group", false);
2623         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2624         final NotificationRecord newGroup = generateNotificationRecord(
2625                 mTestNotificationChannel, 4, "group2", false);
2626         mService.addNotification(parent);
2627         mService.addNotification(child);
2628         mService.addNotification(child2);
2629         mService.addNotification(newGroup);
2630         mService.getBinderService().cancelNotificationsFromListener(null, null);
2631         waitForIdle();
2632         StatusBarNotification[] notifs =
2633                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2634         assertEquals(1, notifs.length);
2635     }
2636 
2637     @Test
testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()2638     public void testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()
2639             throws Exception {
2640         when(mAmi.applyForegroundServiceNotification(
2641                 any(), anyString(), anyInt(), anyString(), anyInt()))
2642                 .thenReturn(SHOW_IMMEDIATELY);
2643         final NotificationRecord parent = generateNotificationRecord(
2644                 mTestNotificationChannel, 1, "group", true);
2645         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2646         final NotificationRecord child = generateNotificationRecord(
2647                 mTestNotificationChannel, 2, "group", false);
2648         final NotificationRecord child2 = generateNotificationRecord(
2649                 mTestNotificationChannel, 3, "group", false);
2650         final NotificationRecord newGroup = generateNotificationRecord(
2651                 mTestNotificationChannel, 4, "group2", false);
2652         mService.addNotification(parent);
2653         mService.addNotification(child);
2654         mService.addNotification(child2);
2655         mService.addNotification(newGroup);
2656         mService.getBinderService().cancelNotificationsFromListener(null, null);
2657         waitForIdle();
2658         StatusBarNotification[] notifs =
2659                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2660         assertEquals(0, notifs.length);
2661     }
2662 
2663     @Test
testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()2664     public void testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()
2665             throws Exception {
2666         when(mAmi.applyForegroundServiceNotification(
2667                 any(), anyString(), anyInt(), anyString(), anyInt()))
2668                 .thenReturn(SHOW_IMMEDIATELY);
2669         final NotificationRecord parent = generateNotificationRecord(
2670                 mTestNotificationChannel, 1, "group", true);
2671         final NotificationRecord child = generateNotificationRecord(
2672                 mTestNotificationChannel, 2, "group", false);
2673         final NotificationRecord child2 = generateNotificationRecord(
2674                 mTestNotificationChannel, 3, "group", false);
2675         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2676         final NotificationRecord newGroup = generateNotificationRecord(
2677                 mTestNotificationChannel, 4, "group2", false);
2678         mService.addNotification(parent);
2679         mService.addNotification(child);
2680         mService.addNotification(child2);
2681         mService.addNotification(newGroup);
2682         mService.getBinderService().cancelNotificationsFromListener(null, null);
2683         waitForIdle();
2684         StatusBarNotification[] notifs =
2685                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2686         assertEquals(0, notifs.length);
2687     }
2688 
2689     @Test
testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent()2690     public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent()
2691             throws Exception {
2692         final NotificationRecord parent = generateNotificationRecord(
2693                 mTestNotificationChannel, 1, "group", true);
2694         parent.getNotification().flags |= FLAG_NO_CLEAR;
2695         final NotificationRecord child = generateNotificationRecord(
2696                 mTestNotificationChannel, 2, "group", false);
2697         final NotificationRecord child2 = generateNotificationRecord(
2698                 mTestNotificationChannel, 3, "group", false);
2699         final NotificationRecord newGroup = generateNotificationRecord(
2700                 mTestNotificationChannel, 4, "group2", false);
2701         mService.addNotification(parent);
2702         mService.addNotification(child);
2703         mService.addNotification(child2);
2704         mService.addNotification(newGroup);
2705         mService.getBinderService().cancelNotificationsFromListener(null, null);
2706         waitForIdle();
2707         StatusBarNotification[] notifs =
2708                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2709         assertEquals(1, notifs.length);
2710     }
2711 
2712     @Test
testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild()2713     public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild()
2714             throws Exception {
2715         final NotificationRecord parent = generateNotificationRecord(
2716                 mTestNotificationChannel, 1, "group", true);
2717         final NotificationRecord child = generateNotificationRecord(
2718                 mTestNotificationChannel, 2, "group", false);
2719         final NotificationRecord child2 = generateNotificationRecord(
2720                 mTestNotificationChannel, 3, "group", false);
2721         child2.getNotification().flags |= FLAG_NO_CLEAR;
2722         final NotificationRecord newGroup = generateNotificationRecord(
2723                 mTestNotificationChannel, 4, "group2", false);
2724         mService.addNotification(parent);
2725         mService.addNotification(child);
2726         mService.addNotification(child2);
2727         mService.addNotification(newGroup);
2728         mService.getBinderService().cancelNotificationsFromListener(null, null);
2729         waitForIdle();
2730         StatusBarNotification[] notifs =
2731                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2732         assertEquals(1, notifs.length);
2733     }
2734 
2735     @Test
testCancelNotificationsFromListener_clearAll_Ongoing()2736     public void testCancelNotificationsFromListener_clearAll_Ongoing()
2737             throws Exception {
2738         final NotificationRecord child2 = generateNotificationRecord(
2739                 mTestNotificationChannel, 3, null, false);
2740         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2741         mService.addNotification(child2);
2742         String[] keys = {child2.getSbn().getKey()};
2743         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2744         waitForIdle();
2745         StatusBarNotification[] notifs =
2746                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2747         assertEquals(1, notifs.length);
2748     }
2749 
2750     @Test
testCancelNotificationsFromListener_clearAll_NoClear()2751     public void testCancelNotificationsFromListener_clearAll_NoClear()
2752             throws Exception {
2753         final NotificationRecord child2 = generateNotificationRecord(
2754                 mTestNotificationChannel, 3, null, false);
2755         child2.getNotification().flags |= FLAG_NO_CLEAR;
2756         mService.addNotification(child2);
2757         mService.getBinderService().cancelNotificationsFromListener(null, null);
2758         waitForIdle();
2759         StatusBarNotification[] notifs =
2760                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2761         assertEquals(1, notifs.length);
2762     }
2763 
2764     @Test
testCancelNotificationsFromListener_clearAll_Fgs()2765     public void testCancelNotificationsFromListener_clearAll_Fgs()
2766             throws Exception {
2767         when(mAmi.applyForegroundServiceNotification(
2768                 any(), anyString(), anyInt(), anyString(), anyInt()))
2769                 .thenReturn(SHOW_IMMEDIATELY);
2770         final NotificationRecord child2 = generateNotificationRecord(
2771                 mTestNotificationChannel, 3, null, false);
2772         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2773         mService.addNotification(child2);
2774         mService.getBinderService().cancelNotificationsFromListener(null, null);
2775         waitForIdle();
2776         StatusBarNotification[] notifs =
2777                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2778         assertEquals(0, notifs.length);
2779     }
2780 
2781     @Test
testCancelNotificationsFromListener_byKey_GroupWithOngoingParent()2782     public void testCancelNotificationsFromListener_byKey_GroupWithOngoingParent()
2783             throws Exception {
2784         final NotificationRecord parent = generateNotificationRecord(
2785                 mTestNotificationChannel, 1, "group", true);
2786         parent.getNotification().flags |= FLAG_ONGOING_EVENT;
2787         final NotificationRecord child = generateNotificationRecord(
2788                 mTestNotificationChannel, 2, "group", false);
2789         final NotificationRecord child2 = generateNotificationRecord(
2790                 mTestNotificationChannel, 3, "group", false);
2791         final NotificationRecord newGroup = generateNotificationRecord(
2792                 mTestNotificationChannel, 4, "group2", false);
2793         mService.addNotification(parent);
2794         mService.addNotification(child);
2795         mService.addNotification(child2);
2796         mService.addNotification(newGroup);
2797         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2798                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2799         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2800         waitForIdle();
2801         StatusBarNotification[] notifs =
2802                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2803         assertEquals(1, notifs.length);
2804     }
2805 
2806     @Test
testCancelNotificationsFromListener_byKey_GroupWithOngoingChild()2807     public void testCancelNotificationsFromListener_byKey_GroupWithOngoingChild()
2808             throws Exception {
2809         final NotificationRecord parent = generateNotificationRecord(
2810                 mTestNotificationChannel, 1, "group", true);
2811         final NotificationRecord child = generateNotificationRecord(
2812                 mTestNotificationChannel, 2, "group", false);
2813         final NotificationRecord child2 = generateNotificationRecord(
2814                 mTestNotificationChannel, 3, "group", false);
2815         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2816         final NotificationRecord newGroup = generateNotificationRecord(
2817                 mTestNotificationChannel, 4, "group2", false);
2818         mService.addNotification(parent);
2819         mService.addNotification(child);
2820         mService.addNotification(child2);
2821         mService.addNotification(newGroup);
2822         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2823                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2824         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2825         waitForIdle();
2826         StatusBarNotification[] notifs =
2827                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2828         assertEquals(1, notifs.length);
2829     }
2830 
2831     @Test
testCancelNotificationsFromListener_byKey_GroupWithFgsParent()2832     public void testCancelNotificationsFromListener_byKey_GroupWithFgsParent()
2833             throws Exception {
2834         when(mAmi.applyForegroundServiceNotification(
2835                 any(), anyString(), anyInt(), anyString(), anyInt()))
2836                 .thenReturn(SHOW_IMMEDIATELY);
2837         final NotificationRecord parent = generateNotificationRecord(
2838                 mTestNotificationChannel, 1, "group", true);
2839         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2840         final NotificationRecord child = generateNotificationRecord(
2841                 mTestNotificationChannel, 2, "group", false);
2842         final NotificationRecord child2 = generateNotificationRecord(
2843                 mTestNotificationChannel, 3, "group", false);
2844         final NotificationRecord newGroup = generateNotificationRecord(
2845                 mTestNotificationChannel, 4, "group2", false);
2846         mService.addNotification(parent);
2847         mService.addNotification(child);
2848         mService.addNotification(child2);
2849         mService.addNotification(newGroup);
2850         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2851                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2852         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2853         waitForIdle();
2854         StatusBarNotification[] notifs =
2855                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2856         assertEquals(0, notifs.length);
2857     }
2858 
2859     @Test
testCancelNotificationsFromListener_byKey_GroupWithFgsChild()2860     public void testCancelNotificationsFromListener_byKey_GroupWithFgsChild()
2861             throws Exception {
2862         when(mAmi.applyForegroundServiceNotification(
2863                 any(), anyString(), anyInt(), anyString(), anyInt()))
2864                 .thenReturn(SHOW_IMMEDIATELY);
2865         final NotificationRecord parent = generateNotificationRecord(
2866                 mTestNotificationChannel, 1, "group", true);
2867         final NotificationRecord child = generateNotificationRecord(
2868                 mTestNotificationChannel, 2, "group", false);
2869         final NotificationRecord child2 = generateNotificationRecord(
2870                 mTestNotificationChannel, 3, "group", false);
2871         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2872         final NotificationRecord newGroup = generateNotificationRecord(
2873                 mTestNotificationChannel, 4, "group2", false);
2874         mService.addNotification(parent);
2875         mService.addNotification(child);
2876         mService.addNotification(child2);
2877         mService.addNotification(newGroup);
2878         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2879                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2880         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2881         waitForIdle();
2882         StatusBarNotification[] notifs =
2883                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2884         assertEquals(0, notifs.length);
2885     }
2886 
2887     @Test
testCancelNotificationsFromListener_byKey_GroupWithNoClearParent()2888     public void testCancelNotificationsFromListener_byKey_GroupWithNoClearParent()
2889             throws Exception {
2890         final NotificationRecord parent = generateNotificationRecord(
2891                 mTestNotificationChannel, 1, "group", true);
2892         parent.getNotification().flags |= FLAG_NO_CLEAR;
2893         final NotificationRecord child = generateNotificationRecord(
2894                 mTestNotificationChannel, 2, "group", false);
2895         final NotificationRecord child2 = generateNotificationRecord(
2896                 mTestNotificationChannel, 3, "group", false);
2897         final NotificationRecord newGroup = generateNotificationRecord(
2898                 mTestNotificationChannel, 4, "group2", false);
2899         mService.addNotification(parent);
2900         mService.addNotification(child);
2901         mService.addNotification(child2);
2902         mService.addNotification(newGroup);
2903         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2904                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2905         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2906         waitForIdle();
2907         StatusBarNotification[] notifs =
2908                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2909         assertEquals(0, notifs.length);
2910     }
2911 
2912     @Test
testCancelNotificationsFromListener_byKey_GroupWithNoClearChild()2913     public void testCancelNotificationsFromListener_byKey_GroupWithNoClearChild()
2914             throws Exception {
2915         final NotificationRecord parent = generateNotificationRecord(
2916                 mTestNotificationChannel, 1, "group", true);
2917         final NotificationRecord child = generateNotificationRecord(
2918                 mTestNotificationChannel, 2, "group", false);
2919         final NotificationRecord child2 = generateNotificationRecord(
2920                 mTestNotificationChannel, 3, "group", false);
2921         child2.getNotification().flags |= FLAG_NO_CLEAR;
2922         final NotificationRecord newGroup = generateNotificationRecord(
2923                 mTestNotificationChannel, 4, "group2", false);
2924         mService.addNotification(parent);
2925         mService.addNotification(child);
2926         mService.addNotification(child2);
2927         mService.addNotification(newGroup);
2928         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2929                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2930         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2931         waitForIdle();
2932         StatusBarNotification[] notifs =
2933                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2934         assertEquals(0, notifs.length);
2935     }
2936 
2937     @Test
testCancelNotificationsFromListener_byKey_Ongoing()2938     public void testCancelNotificationsFromListener_byKey_Ongoing()
2939             throws Exception {
2940         final NotificationRecord child2 = generateNotificationRecord(
2941                 mTestNotificationChannel, 3, null, false);
2942         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2943         mService.addNotification(child2);
2944         String[] keys = {child2.getSbn().getKey()};
2945         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2946         waitForIdle();
2947         StatusBarNotification[] notifs =
2948                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2949         assertEquals(1, notifs.length);
2950     }
2951 
2952     @Test
testCancelNotificationsFromListener_byKey_NoClear()2953     public void testCancelNotificationsFromListener_byKey_NoClear()
2954             throws Exception {
2955         final NotificationRecord child2 = generateNotificationRecord(
2956                 mTestNotificationChannel, 3, null, false);
2957         child2.getNotification().flags |= FLAG_NO_CLEAR;
2958         mService.addNotification(child2);
2959         String[] keys = {child2.getSbn().getKey()};
2960         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2961         waitForIdle();
2962         StatusBarNotification[] notifs =
2963                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2964         assertEquals(0, notifs.length);
2965     }
2966 
2967     @Test
testCancelNotificationsFromListener_byKey_Fgs()2968     public void testCancelNotificationsFromListener_byKey_Fgs()
2969             throws Exception {
2970         when(mAmi.applyForegroundServiceNotification(
2971                 any(), anyString(), anyInt(), anyString(), anyInt()))
2972                 .thenReturn(SHOW_IMMEDIATELY);
2973         final NotificationRecord child2 = generateNotificationRecord(
2974                 mTestNotificationChannel, 3, null, false);
2975         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2976         mService.addNotification(child2);
2977         String[] keys = {child2.getSbn().getKey()};
2978         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2979         waitForIdle();
2980         StatusBarNotification[] notifs =
2981                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2982         assertEquals(0, notifs.length);
2983     }
2984 
2985     @Test
testGroupInstanceIds()2986     public void testGroupInstanceIds() throws Exception {
2987         final NotificationRecord group1 = generateNotificationRecord(
2988                 mTestNotificationChannel, 1, "group1", true);
2989         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds",
2990                 group1.getSbn().getId(), group1.getSbn().getNotification(),
2991                 group1.getSbn().getUserId());
2992         waitForIdle();
2993 
2994         // same group, child, should be returned
2995         final NotificationRecord group1Child = generateNotificationRecord(
2996                 mTestNotificationChannel, 2, "group1", false);
2997         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds",
2998                 group1Child.getSbn().getId(),
2999                 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
3000         waitForIdle();
3001 
3002         assertEquals(2, mNotificationRecordLogger.numCalls());
3003         assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
3004                 mNotificationRecordLogger.get(1).groupInstanceId.getId());
3005     }
3006 
3007     @Test
testFindGroupNotificationsLocked()3008     public void testFindGroupNotificationsLocked() throws Exception {
3009         // make sure the same notification can be found in both lists and returned
3010         final NotificationRecord group1 = generateNotificationRecord(
3011                 mTestNotificationChannel, 1, "group1", true);
3012         mService.addEnqueuedNotification(group1);
3013         mService.addNotification(group1);
3014 
3015         // should not be returned
3016         final NotificationRecord group2 = generateNotificationRecord(
3017                 mTestNotificationChannel, 2, "group2", true);
3018         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
3019                 group2.getSbn().getId(), group2.getSbn().getNotification(),
3020                 group2.getSbn().getUserId());
3021         waitForIdle();
3022 
3023         // should not be returned
3024         final NotificationRecord nonGroup = generateNotificationRecord(
3025                 mTestNotificationChannel, 3, null, false);
3026         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
3027                 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
3028                 nonGroup.getSbn().getUserId());
3029         waitForIdle();
3030 
3031         // same group, child, should be returned
3032         final NotificationRecord group1Child = generateNotificationRecord(
3033                 mTestNotificationChannel, 4, "group1", false);
3034         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
3035                 group1Child.getSbn().getId(),
3036                 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
3037         waitForIdle();
3038 
3039         List<NotificationRecord> inGroup1 =
3040                 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
3041                         group1.getSbn().getUserId());
3042         assertEquals(3, inGroup1.size());
3043         for (NotificationRecord record : inGroup1) {
3044             assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
3045             assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
3046         }
3047     }
3048 
3049     @Test
testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing()3050     public void testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing() throws Exception {
3051         final NotificationRecord notif = generateNotificationRecord(
3052                 mTestNotificationChannel, 1, "group", true);
3053         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
3054         mService.addNotification(notif);
3055         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
3056                 Notification.FLAG_ONGOING_EVENT, notif.getUserId(), REASON_CANCEL);
3057         waitForIdle();
3058         StatusBarNotification[] notifs =
3059                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
3060         assertEquals(0, notifs.length);
3061     }
3062 
3063     @Test
testAppInitiatedCancelAllNotifications_CancelsOngoingFlag()3064     public void testAppInitiatedCancelAllNotifications_CancelsOngoingFlag() throws Exception {
3065         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
3066         sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
3067         mBinderService.enqueueNotificationWithTag(PKG, PKG,
3068                 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
3069                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3070         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
3071         waitForIdle();
3072         StatusBarNotification[] notifs =
3073                 mBinderService.getActiveNotifications(sbn.getPackageName());
3074         assertEquals(0, notifs.length);
3075     }
3076 
3077     @Test
testCancelAllNotificationsInt_CancelsOngoingFlag()3078     public void testCancelAllNotificationsInt_CancelsOngoingFlag() throws Exception {
3079         final NotificationRecord notif = generateNotificationRecord(
3080                 mTestNotificationChannel, 1, "group", true);
3081         notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
3082         mService.addNotification(notif);
3083         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0,
3084                 notif.getUserId(), REASON_CANCEL);
3085         waitForIdle();
3086         StatusBarNotification[] notifs =
3087                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
3088         assertEquals(0, notifs.length);
3089     }
3090 
3091     @Test
testUserInitiatedCancelAllWithGroup_OngoingFlag()3092     public void testUserInitiatedCancelAllWithGroup_OngoingFlag() throws Exception {
3093         final NotificationRecord parent = generateNotificationRecord(
3094                 mTestNotificationChannel, 1, "group", true);
3095         final NotificationRecord child = generateNotificationRecord(
3096                 mTestNotificationChannel, 2, "group", false);
3097         final NotificationRecord child2 = generateNotificationRecord(
3098                 mTestNotificationChannel, 3, "group", false);
3099         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
3100         final NotificationRecord newGroup = generateNotificationRecord(
3101                 mTestNotificationChannel, 4, "group2", false);
3102         mService.addNotification(parent);
3103         mService.addNotification(child);
3104         mService.addNotification(child2);
3105         mService.addNotification(newGroup);
3106         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
3107                 parent.getUserId());
3108         waitForIdle();
3109         StatusBarNotification[] notifs =
3110                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
3111         assertEquals(1, notifs.length);
3112     }
3113 
3114     @Test
testUserInitiatedCancelAllWithGroup_NoClearFlag()3115     public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
3116         final NotificationRecord parent = generateNotificationRecord(
3117                 mTestNotificationChannel, 1, "group", true);
3118         final NotificationRecord child = generateNotificationRecord(
3119                 mTestNotificationChannel, 2, "group", false);
3120         final NotificationRecord child2 = generateNotificationRecord(
3121                 mTestNotificationChannel, 3, "group", false);
3122         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
3123         final NotificationRecord newGroup = generateNotificationRecord(
3124                 mTestNotificationChannel, 4, "group2", false);
3125         mService.addNotification(parent);
3126         mService.addNotification(child);
3127         mService.addNotification(child2);
3128         mService.addNotification(newGroup);
3129         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
3130                 parent.getUserId());
3131         waitForIdle();
3132         StatusBarNotification[] notifs =
3133                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
3134         assertEquals(1, notifs.length);
3135     }
3136 
3137     @Test
testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()3138     public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
3139         when(mAmi.applyForegroundServiceNotification(
3140                 any(), anyString(), anyInt(), anyString(), anyInt()))
3141                 .thenReturn(SHOW_IMMEDIATELY);
3142         final NotificationRecord parent = generateNotificationRecord(
3143                 mTestNotificationChannel, 1, "group", true);
3144         final NotificationRecord child = generateNotificationRecord(
3145                 mTestNotificationChannel, 2, "group", false);
3146         final NotificationRecord child2 = generateNotificationRecord(
3147                 mTestNotificationChannel, 3, "group", false);
3148         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
3149         final NotificationRecord newGroup = generateNotificationRecord(
3150                 mTestNotificationChannel, 4, "group2", false);
3151         mService.addNotification(parent);
3152         mService.addNotification(child);
3153         mService.addNotification(child2);
3154         mService.addNotification(newGroup);
3155         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
3156                 parent.getUserId());
3157         waitForIdle();
3158         StatusBarNotification[] notifs =
3159                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
3160         assertEquals(0, notifs.length);
3161     }
3162 
3163     @Test
testDefaultChannelUpdatesApp_postMigrationToPermissions()3164     public void testDefaultChannelUpdatesApp_postMigrationToPermissions() throws Exception {
3165         final NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
3166                 PKG_N_MR1, ActivityManager.getCurrentUser(), PKG_N_MR1,
3167                 NotificationChannel.DEFAULT_CHANNEL_ID);
3168         defaultChannel.setImportance(IMPORTANCE_NONE);
3169 
3170         mBinderService.updateNotificationChannelForPackage(PKG_N_MR1, mUid, defaultChannel);
3171 
3172         verify(mPermissionHelper).setNotificationPermission(
3173                 PKG_N_MR1, ActivityManager.getCurrentUser(), false, true);
3174     }
3175 
3176     @Test
testPostNotification_appPermissionFixed()3177     public void testPostNotification_appPermissionFixed() throws Exception {
3178         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
3179         when(mPermissionHelper.isPermissionFixed(PKG, 0)).thenReturn(true);
3180 
3181         NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel);
3182         mBinderService.enqueueNotificationWithTag(PKG, PKG,
3183                 "testPostNotification_appPermissionFixed", 0,
3184                 temp.getNotification(), 0);
3185         waitForIdle();
3186         assertThat(mService.getNotificationRecordCount()).isEqualTo(1);
3187         StatusBarNotification[] notifs =
3188                 mBinderService.getActiveNotifications(PKG);
3189         assertThat(mService.getNotificationRecord(notifs[0].getKey()).isImportanceFixed()).isTrue();
3190     }
3191 
3192     @Test
testSummaryNotification_appPermissionFixed()3193     public void testSummaryNotification_appPermissionFixed() {
3194         NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel);
3195         mService.addNotification(temp);
3196 
3197         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
3198         when(mPermissionHelper.isPermissionFixed(PKG, temp.getUserId())).thenReturn(true);
3199 
3200         NotificationRecord r = mService.createAutoGroupSummary(
3201                 temp.getUserId(), temp.getSbn().getPackageName(), temp.getKey(), 0);
3202 
3203         assertThat(r.isImportanceFixed()).isTrue();
3204     }
3205 
3206     @Test
testTvExtenderChannelOverride_onTv()3207     public void testTvExtenderChannelOverride_onTv() throws Exception {
3208         mService.setIsTelevision(true);
3209         mService.setPreferencesHelper(mPreferencesHelper);
3210         when(mPreferencesHelper.getNotificationChannel(
3211                 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
3212                         new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
3213 
3214         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
3215         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
3216                 generateNotificationRecord(null, tv).getNotification(), 0);
3217         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
3218                 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
3219     }
3220 
3221     @Test
testTvExtenderChannelOverride_notOnTv()3222     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
3223         mService.setIsTelevision(false);
3224         mService.setPreferencesHelper(mPreferencesHelper);
3225         when(mPreferencesHelper.getNotificationChannel(
3226                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
3227                 mTestNotificationChannel);
3228 
3229         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
3230         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
3231                 0, generateNotificationRecord(null, tv).getNotification(), 0);
3232         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
3233                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
3234                 anyBoolean(), anyBoolean());
3235     }
3236 
3237     @Test
onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()3238     public void onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()
3239             throws RemoteException {
3240         // Have preexisting posted notifications from revoked package and other packages.
3241         mService.addNotification(new NotificationRecord(mContext,
3242                 generateSbn("revoked", 1001, 1, 0), mTestNotificationChannel));
3243         mService.addNotification(new NotificationRecord(mContext,
3244                 generateSbn("other", 1002, 2, 0), mTestNotificationChannel));
3245         // Have preexisting enqueued notifications from revoked package and other packages.
3246         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3247                 generateSbn("revoked", 1001, 3, 0), mTestNotificationChannel));
3248         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3249                 generateSbn("other", 1002, 4, 0), mTestNotificationChannel));
3250         assertThat(mService.mNotificationList).hasSize(2);
3251         assertThat(mService.mEnqueuedNotifications).hasSize(2);
3252 
3253         when(mPackageManagerInternal.getPackageUid("revoked", 0, 0)).thenReturn(1001);
3254         when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(false);
3255 
3256         mOnPermissionChangeListener.onOpChanged(
3257                 AppOpsManager.OPSTR_POST_NOTIFICATION, "revoked", 0);
3258         waitForIdle();
3259 
3260         assertThat(mService.mNotificationList).hasSize(1);
3261         assertThat(mService.mNotificationList.get(0).getSbn().getPackageName()).isEqualTo("other");
3262         assertThat(mService.mEnqueuedNotifications).hasSize(1);
3263         assertThat(mService.mEnqueuedNotifications.get(0).getSbn().getPackageName()).isEqualTo(
3264                 "other");
3265     }
3266 
3267     @Test
onOpChanged_permissionStillGranted_notificationsAreNotAffected()3268     public void onOpChanged_permissionStillGranted_notificationsAreNotAffected()
3269             throws RemoteException {
3270         // NOTE: This combination (receiving the onOpChanged broadcast for a package, the permission
3271         // being now granted, AND having previously posted notifications from said package) should
3272         // never happen (if we trust the broadcasts are correct). So this test is for a what-if
3273         // scenario, to verify we still handle it reasonably.
3274 
3275         // Have preexisting posted notifications from specific package and other packages.
3276         mService.addNotification(new NotificationRecord(mContext,
3277                 generateSbn("granted", 1001, 1, 0), mTestNotificationChannel));
3278         mService.addNotification(new NotificationRecord(mContext,
3279                 generateSbn("other", 1002, 2, 0), mTestNotificationChannel));
3280         // Have preexisting enqueued notifications from specific package and other packages.
3281         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3282                 generateSbn("granted", 1001, 3, 0), mTestNotificationChannel));
3283         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3284                 generateSbn("other", 1002, 4, 0), mTestNotificationChannel));
3285         assertThat(mService.mNotificationList).hasSize(2);
3286         assertThat(mService.mEnqueuedNotifications).hasSize(2);
3287 
3288         when(mPackageManagerInternal.getPackageUid("granted", 0, 0)).thenReturn(1001);
3289         when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(true);
3290 
3291         mOnPermissionChangeListener.onOpChanged(
3292                 AppOpsManager.OPSTR_POST_NOTIFICATION, "granted", 0);
3293         waitForIdle();
3294 
3295         assertThat(mService.mNotificationList).hasSize(2);
3296         assertThat(mService.mEnqueuedNotifications).hasSize(2);
3297     }
3298 
3299     @Test
onOpChanged_notInitializedUser_ignored()3300     public void onOpChanged_notInitializedUser_ignored() throws RemoteException {
3301         when(mUmInternal.isUserInitialized(eq(0))).thenReturn(false);
3302 
3303         mOnPermissionChangeListener.onOpChanged(
3304                 AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0);
3305         waitForIdle();
3306 
3307         // We early-exited and didn't even query PM for package details.
3308         verify(mPackageManagerInternal, never()).getPackageUid(any(), anyLong(), anyInt());
3309     }
3310 
3311     @Test
setNotificationsEnabledForPackage_disabling_clearsNotifications()3312     public void setNotificationsEnabledForPackage_disabling_clearsNotifications() throws Exception {
3313         mService.addNotification(new NotificationRecord(mContext,
3314                 generateSbn("package", 1001, 1, 0), mTestNotificationChannel));
3315         assertThat(mService.mNotificationList).hasSize(1);
3316         when(mPackageManagerInternal.getPackageUid("package", 0, 0)).thenReturn(1001);
3317         when(mPermissionHelper.hasRequestedPermission(any(), eq("package"), anyInt())).thenReturn(
3318                 true);
3319 
3320         // Start with granted permission and simulate effect of revoking it.
3321         when(mPermissionHelper.hasPermission(1001)).thenReturn(true);
3322         doAnswer(invocation -> {
3323             when(mPermissionHelper.hasPermission(1001)).thenReturn(false);
3324             mOnPermissionChangeListener.onOpChanged(
3325                     AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0);
3326             return null;
3327         }).when(mPermissionHelper).setNotificationPermission("package", 0, false, true);
3328 
3329         mBinderService.setNotificationsEnabledForPackage("package", 1001, false);
3330         waitForIdle();
3331 
3332         assertThat(mService.mNotificationList).hasSize(0);
3333 
3334         mTestableLooper.moveTimeForward(500);
3335         waitForIdle();
3336         verify(mContext).sendBroadcastAsUser(any(), eq(UserHandle.of(0)), eq(null));
3337     }
3338 
3339     @Test
testUpdateAppNotifyCreatorBlock()3340     public void testUpdateAppNotifyCreatorBlock() throws Exception {
3341         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
3342 
3343         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
3344         Thread.sleep(500);
3345         waitForIdle();
3346 
3347         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3348         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3349 
3350         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
3351                 captor.getValue().getAction());
3352         assertEquals(PKG, captor.getValue().getPackage());
3353         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
3354     }
3355 
3356     @Test
testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()3357     public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
3358         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
3359 
3360         mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
3361         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
3362     }
3363 
3364     @Test
testUpdateAppNotifyCreatorUnblock()3365     public void testUpdateAppNotifyCreatorUnblock() throws Exception {
3366         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
3367 
3368         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, true);
3369         Thread.sleep(500);
3370         waitForIdle();
3371 
3372         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3373         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3374 
3375         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
3376                 captor.getValue().getAction());
3377         assertEquals(PKG, captor.getValue().getPackage());
3378         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
3379     }
3380 
3381     @Test
testUpdateChannelNotifyCreatorBlock()3382     public void testUpdateChannelNotifyCreatorBlock() throws Exception {
3383         mService.setPreferencesHelper(mPreferencesHelper);
3384         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3385                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3386                 .thenReturn(mTestNotificationChannel);
3387 
3388         NotificationChannel updatedChannel =
3389                 new NotificationChannel(mTestNotificationChannel.getId(),
3390                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
3391 
3392         mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
3393         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3394         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3395 
3396         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
3397                 captor.getValue().getAction());
3398         assertEquals(PKG, captor.getValue().getPackage());
3399         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
3400                         NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
3401         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3402     }
3403 
3404     @Test
testUpdateChannelNotifyCreatorUnblock()3405     public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
3406         NotificationChannel existingChannel =
3407                 new NotificationChannel(mTestNotificationChannel.getId(),
3408                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
3409         mService.setPreferencesHelper(mPreferencesHelper);
3410         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3411                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3412                 .thenReturn(existingChannel);
3413 
3414         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
3415         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3416         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3417 
3418         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
3419                 captor.getValue().getAction());
3420         assertEquals(PKG, captor.getValue().getPackage());
3421         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
3422                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
3423         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3424     }
3425 
3426     @Test
testUpdateChannelNoNotifyCreatorOtherChanges()3427     public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
3428         NotificationChannel existingChannel =
3429                 new NotificationChannel(mTestNotificationChannel.getId(),
3430                         mTestNotificationChannel.getName(), IMPORTANCE_MAX);
3431         mService.setPreferencesHelper(mPreferencesHelper);
3432         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3433                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3434                 .thenReturn(existingChannel);
3435 
3436         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
3437         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
3438     }
3439 
3440     @Test
testUpdateGroupNotifyCreatorBlock()3441     public void testUpdateGroupNotifyCreatorBlock() throws Exception {
3442         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
3443         mService.setPreferencesHelper(mPreferencesHelper);
3444         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
3445                 eq(PKG), anyInt()))
3446                 .thenReturn(existing);
3447 
3448         NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
3449         updated.setBlocked(true);
3450 
3451         mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
3452         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3453         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3454 
3455         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
3456                 captor.getValue().getAction());
3457         assertEquals(PKG, captor.getValue().getPackage());
3458         assertEquals(existing.getId(), captor.getValue().getStringExtra(
3459                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
3460         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3461     }
3462 
3463     @Test
testUpdateGroupNotifyCreatorUnblock()3464     public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
3465         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
3466         existing.setBlocked(true);
3467         mService.setPreferencesHelper(mPreferencesHelper);
3468         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
3469                 eq(PKG), anyInt()))
3470                 .thenReturn(existing);
3471 
3472         mBinderService.updateNotificationChannelGroupForPackage(
3473                 PKG, 0, new NotificationChannelGroup("id", "name"));
3474         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3475         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3476 
3477         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
3478                 captor.getValue().getAction());
3479         assertEquals(PKG, captor.getValue().getPackage());
3480         assertEquals(existing.getId(), captor.getValue().getStringExtra(
3481                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
3482         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3483     }
3484 
3485     @Test
testUpdateGroupNoNotifyCreatorOtherChanges()3486     public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
3487         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
3488         mService.setPreferencesHelper(mPreferencesHelper);
3489         when(mPreferencesHelper.getNotificationChannelGroup(
3490                 eq(existing.getId()), eq(PKG), anyInt()))
3491                 .thenReturn(existing);
3492 
3493         mBinderService.updateNotificationChannelGroupForPackage(
3494                 PKG, 0, new NotificationChannelGroup("id", "new name"));
3495         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
3496     }
3497 
3498     @Test
testCreateChannelNotifyListener()3499     public void testCreateChannelNotifyListener() throws Exception {
3500         when(mCompanionMgr.getAssociations(PKG, mUserId))
3501                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3502         mService.setPreferencesHelper(mPreferencesHelper);
3503         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3504                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3505                 .thenReturn(mTestNotificationChannel);
3506         NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
3507         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3508                 eq(channel2.getId()), anyBoolean()))
3509                 .thenReturn(channel2);
3510         when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
3511                 eq(channel2), anyBoolean(), anyBoolean(), anyInt(), anyBoolean()))
3512                 .thenReturn(true);
3513 
3514         reset(mListeners);
3515         mBinderService.createNotificationChannels(PKG,
3516                 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
3517         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3518                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3519                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3520         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
3521                 eq(Process.myUserHandle()), eq(channel2),
3522                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3523     }
3524 
3525     @Test
testCreateChannelGroupNotifyListener()3526     public void testCreateChannelGroupNotifyListener() throws Exception {
3527         when(mCompanionMgr.getAssociations(PKG, mUserId))
3528                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3529         mService.setPreferencesHelper(mPreferencesHelper);
3530         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
3531         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
3532 
3533         reset(mListeners);
3534         mBinderService.createNotificationChannelGroups(PKG,
3535                 new ParceledListSlice(Arrays.asList(group1, group2)));
3536         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
3537                 eq(Process.myUserHandle()), eq(group1),
3538                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3539         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
3540                 eq(Process.myUserHandle()), eq(group2),
3541                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3542     }
3543 
3544     @Test
testUpdateChannelNotifyListener()3545     public void testUpdateChannelNotifyListener() throws Exception {
3546         when(mCompanionMgr.getAssociations(PKG, mUserId))
3547                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3548         mService.setPreferencesHelper(mPreferencesHelper);
3549         mTestNotificationChannel.setLightColor(Color.CYAN);
3550         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3551                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3552                 .thenReturn(mTestNotificationChannel);
3553 
3554         reset(mListeners);
3555         mBinderService.updateNotificationChannelForPackage(PKG, mUid, mTestNotificationChannel);
3556         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
3557                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3558                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3559     }
3560 
3561     @Test
testDeleteChannelNotifyListener()3562     public void testDeleteChannelNotifyListener() throws Exception {
3563         when(mCompanionMgr.getAssociations(PKG, mUserId))
3564                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3565         mService.setPreferencesHelper(mPreferencesHelper);
3566         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3567                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3568                 .thenReturn(mTestNotificationChannel);
3569         when(mPreferencesHelper.deleteNotificationChannel(eq(PKG), anyInt(),
3570                 eq(mTestNotificationChannel.getId()),  anyInt(), anyBoolean())).thenReturn(true);
3571         reset(mListeners);
3572         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
3573         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
3574                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3575                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
3576     }
3577 
3578     @Test
testDeleteChannelOnlyDoExtraWorkIfExisted()3579     public void testDeleteChannelOnlyDoExtraWorkIfExisted() throws Exception {
3580         when(mCompanionMgr.getAssociations(PKG, mUserId))
3581                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3582         mService.setPreferencesHelper(mPreferencesHelper);
3583         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3584                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3585                 .thenReturn(null);
3586         reset(mListeners);
3587         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
3588         verifyNoMoreInteractions(mListeners);
3589         verifyNoMoreInteractions(mHistoryManager);
3590     }
3591 
3592     @Test
testDeleteChannelGroupNotifyListener()3593     public void testDeleteChannelGroupNotifyListener() throws Exception {
3594         when(mCompanionMgr.getAssociations(PKG, mUserId))
3595                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3596         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
3597         mService.setPreferencesHelper(mPreferencesHelper);
3598         when(mPreferencesHelper.getNotificationChannelGroupWithChannels(
3599                 eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean()))
3600                 .thenReturn(ncg);
3601         reset(mListeners);
3602         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
3603         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
3604                 eq(Process.myUserHandle()), eq(ncg),
3605                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
3606     }
3607 
3608     @Test
testDeleteChannelGroupChecksForFgses()3609     public void testDeleteChannelGroupChecksForFgses() throws Exception {
3610         when(mCompanionMgr.getAssociations(PKG, mUserId))
3611                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3612         CountDownLatch latch = new CountDownLatch(2);
3613         mService.createNotificationChannelGroup(
3614                 PKG, mUid, new NotificationChannelGroup("group", "group"), true, false);
3615         new Thread(() -> {
3616             NotificationChannel notificationChannel = new NotificationChannel("id", "id",
3617                     NotificationManager.IMPORTANCE_HIGH);
3618             notificationChannel.setGroup("group");
3619             ParceledListSlice<NotificationChannel> pls =
3620                     new ParceledListSlice(ImmutableList.of(notificationChannel));
3621             try {
3622                 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
3623             } catch (RemoteException e) {
3624                 throw new RuntimeException(e);
3625             }
3626             latch.countDown();
3627         }).start();
3628         new Thread(() -> {
3629             try {
3630                 synchronized (this) {
3631                     wait(5000);
3632                 }
3633                 mService.createNotificationChannelGroup(PKG, mUid,
3634                         new NotificationChannelGroup("new", "new group"), true, false);
3635                 NotificationChannel notificationChannel =
3636                         new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
3637                 notificationChannel.setGroup("new");
3638                 ParceledListSlice<NotificationChannel> pls =
3639                         new ParceledListSlice(ImmutableList.of(notificationChannel));
3640                 try {
3641                 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
3642                 mBinderService.deleteNotificationChannelGroup(PKG, "group");
3643                 } catch (RemoteException e) {
3644                     throw new RuntimeException(e);
3645                 }
3646             } catch (Exception e) {
3647                 e.printStackTrace();
3648             }
3649             latch.countDown();
3650         }).start();
3651 
3652         latch.await();
3653         verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString());
3654     }
3655 
3656     @Test
testUpdateNotificationChannelFromPrivilegedListener_success()3657     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
3658         mService.setPreferencesHelper(mPreferencesHelper);
3659         when(mCompanionMgr.getAssociations(PKG, mUserId))
3660                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3661         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3662                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3663                 .thenReturn(mTestNotificationChannel);
3664 
3665         mBinderService.updateNotificationChannelFromPrivilegedListener(
3666                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
3667 
3668         verify(mPreferencesHelper, times(1)).updateNotificationChannel(
3669                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3670 
3671         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3672                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3673                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3674     }
3675 
3676     @Test
testUpdateNotificationChannelFromPrivilegedListener_noAccess()3677     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
3678         mService.setPreferencesHelper(mPreferencesHelper);
3679         when(mCompanionMgr.getAssociations(PKG, mUserId))
3680                 .thenReturn(emptyList());
3681 
3682         try {
3683             mBinderService.updateNotificationChannelFromPrivilegedListener(
3684                     null, PKG, Process.myUserHandle(), mTestNotificationChannel);
3685             fail("listeners that don't have a companion device shouldn't be able to call this");
3686         } catch (SecurityException e) {
3687             // pass
3688         }
3689 
3690         verify(mPreferencesHelper, never()).updateNotificationChannel(
3691                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3692 
3693         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3694                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3695                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3696     }
3697 
3698     @Test
testUpdateNotificationChannelFromPrivilegedListener_badUser()3699     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
3700         mService.setPreferencesHelper(mPreferencesHelper);
3701         when(mCompanionMgr.getAssociations(PKG, mUserId))
3702                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3703         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3704         mListener.component = new ComponentName(PKG, PKG);
3705         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3706         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3707 
3708         try {
3709             mBinderService.updateNotificationChannelFromPrivilegedListener(
3710                     null, PKG, UserHandle.ALL, mTestNotificationChannel);
3711             fail("incorrectly allowed a change to a user listener cannot see");
3712         } catch (SecurityException e) {
3713             // pass
3714         }
3715 
3716         verify(mPreferencesHelper, never()).updateNotificationChannel(
3717                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3718 
3719         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3720                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3721                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3722     }
3723 
3724     @Test
testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission()3725     public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission()
3726             throws Exception {
3727         mService.setPreferencesHelper(mPreferencesHelper);
3728         when(mCompanionMgr.getAssociations(PKG, mUserId))
3729                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3730         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3731                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3732                 .thenReturn(mTestNotificationChannel);
3733 
3734         final Uri soundUri = Uri.parse("content://media/test/sound/uri");
3735         final NotificationChannel updatedNotificationChannel = new NotificationChannel(
3736                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
3737         updatedNotificationChannel.setSound(soundUri,
3738                 updatedNotificationChannel.getAudioAttributes());
3739 
3740         doThrow(new SecurityException("no access")).when(mUgmInternal)
3741                 .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri),
3742                 anyInt(), eq(Process.myUserHandle().getIdentifier()));
3743 
3744         assertThrows(SecurityException.class,
3745                 () -> mBinderService.updateNotificationChannelFromPrivilegedListener(null, PKG,
3746                 Process.myUserHandle(), updatedNotificationChannel));
3747 
3748         verify(mPreferencesHelper, never()).updateNotificationChannel(
3749                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3750 
3751         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3752                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3753                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3754     }
3755 
3756     @Test
testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission_sameSound()3757     public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission_sameSound()
3758             throws Exception {
3759         mService.setPreferencesHelper(mPreferencesHelper);
3760         when(mCompanionMgr.getAssociations(PKG, mUserId))
3761                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3762         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3763                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3764                 .thenReturn(mTestNotificationChannel);
3765 
3766         final Uri soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
3767         final NotificationChannel updatedNotificationChannel = new NotificationChannel(
3768                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
3769         updatedNotificationChannel.setSound(soundUri,
3770                 updatedNotificationChannel.getAudioAttributes());
3771 
3772         doThrow(new SecurityException("no access")).when(mUgmInternal)
3773                 .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri),
3774                     anyInt(), eq(Process.myUserHandle().getIdentifier()));
3775 
3776         mBinderService.updateNotificationChannelFromPrivilegedListener(
3777                 null, PKG, Process.myUserHandle(), updatedNotificationChannel);
3778 
3779         verify(mPreferencesHelper, times(1)).updateNotificationChannel(
3780                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3781 
3782         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3783                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3784                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3785     }
3786 
3787     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_success()3788     public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
3789         mService.setPreferencesHelper(mPreferencesHelper);
3790         when(mCompanionMgr.getAssociations(PKG, mUserId))
3791                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3792 
3793         mBinderService.getNotificationChannelsFromPrivilegedListener(
3794                 null, PKG, Process.myUserHandle());
3795 
3796         verify(mPreferencesHelper, times(1)).getNotificationChannels(
3797                 anyString(), anyInt(), anyBoolean());
3798     }
3799 
3800     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()3801     public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
3802         mService.setPreferencesHelper(mPreferencesHelper);
3803         when(mCompanionMgr.getAssociations(PKG, mUserId))
3804                 .thenReturn(emptyList());
3805 
3806         try {
3807             mBinderService.getNotificationChannelsFromPrivilegedListener(
3808                     null, PKG, Process.myUserHandle());
3809             fail("listeners that don't have a companion device shouldn't be able to call this");
3810         } catch (SecurityException e) {
3811             // pass
3812         }
3813 
3814         verify(mPreferencesHelper, never()).getNotificationChannels(
3815                 anyString(), anyInt(), anyBoolean());
3816     }
3817 
3818     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_success()3819     public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
3820             throws Exception {
3821         mService.setPreferencesHelper(mPreferencesHelper);
3822         when(mCompanionMgr.getAssociations(PKG, mUserId))
3823                 .thenReturn(emptyList());
3824         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
3825 
3826         mBinderService.getNotificationChannelsFromPrivilegedListener(
3827                 null, PKG, Process.myUserHandle());
3828 
3829         verify(mPreferencesHelper, times(1)).getNotificationChannels(
3830                 anyString(), anyInt(), anyBoolean());
3831     }
3832 
3833     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()3834     public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
3835             throws Exception {
3836         mService.setPreferencesHelper(mPreferencesHelper);
3837         when(mCompanionMgr.getAssociations(PKG, mUserId))
3838                 .thenReturn(emptyList());
3839         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
3840 
3841         try {
3842             mBinderService.getNotificationChannelsFromPrivilegedListener(
3843                     null, PKG, Process.myUserHandle());
3844             fail("listeners that don't have a companion device shouldn't be able to call this");
3845         } catch (SecurityException e) {
3846             // pass
3847         }
3848 
3849         verify(mPreferencesHelper, never()).getNotificationChannels(
3850                 anyString(), anyInt(), anyBoolean());
3851     }
3852 
3853     @Test
testGetNotificationChannelFromPrivilegedListener_badUser()3854     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
3855         mService.setPreferencesHelper(mPreferencesHelper);
3856         when(mCompanionMgr.getAssociations(PKG, mUserId))
3857                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3858         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3859         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3860         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3861 
3862         try {
3863             mBinderService.getNotificationChannelsFromPrivilegedListener(
3864                     null, PKG, Process.myUserHandle());
3865             fail("listener getting channels from a user they cannot see");
3866         } catch (SecurityException e) {
3867             // pass
3868         }
3869 
3870         verify(mPreferencesHelper, never()).getNotificationChannels(
3871                 anyString(), anyInt(), anyBoolean());
3872     }
3873 
3874     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_success()3875     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
3876         mService.setPreferencesHelper(mPreferencesHelper);
3877         when(mCompanionMgr.getAssociations(PKG, mUserId))
3878                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3879 
3880         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
3881                 null, PKG, Process.myUserHandle());
3882 
3883         verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
3884     }
3885 
3886     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()3887     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
3888         mService.setPreferencesHelper(mPreferencesHelper);
3889         when(mCompanionMgr.getAssociations(PKG, mUserId))
3890                 .thenReturn(emptyList());
3891 
3892         try {
3893             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
3894                     null, PKG, Process.myUserHandle());
3895             fail("listeners that don't have a companion device shouldn't be able to call this");
3896         } catch (SecurityException e) {
3897             // pass
3898         }
3899 
3900         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
3901     }
3902 
3903     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_badUser()3904     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
3905         mService.setPreferencesHelper(mPreferencesHelper);
3906         when(mCompanionMgr.getAssociations(PKG, mUserId))
3907                 .thenReturn(emptyList());
3908         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3909         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3910         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3911         try {
3912             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
3913                     null, PKG, Process.myUserHandle());
3914             fail("listeners that don't have a companion device shouldn't be able to call this");
3915         } catch (SecurityException e) {
3916             // pass
3917         }
3918 
3919         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
3920     }
3921 
3922     @Test
testHasCompanionDevice_failure()3923     public void testHasCompanionDevice_failure() throws Exception {
3924         when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
3925                 new IllegalArgumentException());
3926         mService.hasCompanionDevice(mListener);
3927     }
3928 
3929     @Test
testHasCompanionDevice_noService()3930     public void testHasCompanionDevice_noService() {
3931         NotificationManagerService noManService =
3932                 new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
3933                 mNotificationInstanceIdSequence);
3934 
3935         assertFalse(noManService.hasCompanionDevice(mListener));
3936     }
3937 
3938     @Test
testCrossUserSnooze()3939     public void testCrossUserSnooze() {
3940         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10);
3941         mService.addNotification(r);
3942         NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0);
3943         mService.addNotification(r2);
3944 
3945         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3946         mListener.component = new ComponentName(PKG, PKG);
3947         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3948         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3949 
3950         mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener);
3951 
3952         verify(mWorkerHandler, never()).post(
3953                 any(NotificationManagerService.SnoozeNotificationRunnable.class));
3954     }
3955 
3956     @Test
testSameUserSnooze()3957     public void testSameUserSnooze() {
3958         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10);
3959         mService.addNotification(r);
3960         NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0);
3961         mService.addNotification(r2);
3962 
3963         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3964         mListener.component = new ComponentName(PKG, PKG);
3965         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(true);
3966         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3967 
3968         mService.snoozeNotificationInt(r2.getKey(), 1000, null, mListener);
3969 
3970         verify(mWorkerHandler).post(
3971                 any(NotificationManagerService.SnoozeNotificationRunnable.class));
3972     }
3973 
3974     @Test
testSnoozeRunnable_tooManySnoozed_singleNotification()3975     public void testSnoozeRunnable_tooManySnoozed_singleNotification() {
3976         final NotificationRecord notification = generateNotificationRecord(
3977                 mTestNotificationChannel, 1, null, true);
3978         mService.addNotification(notification);
3979 
3980         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
3981         when(mSnoozeHelper.canSnooze(1)).thenReturn(false);
3982 
3983         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
3984                 mService.new SnoozeNotificationRunnable(
3985                         notification.getKey(), 100, null);
3986         snoozeNotificationRunnable.run();
3987 
3988         verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
3989         assertThat(mService.getNotificationRecordCount()).isEqualTo(1);
3990     }
3991 
3992     @Test
testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification()3993     public void testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification() {
3994         final NotificationRecord notification = generateNotificationRecord(
3995                 mTestNotificationChannel, 1, "group", true);
3996         final NotificationRecord notificationChild = generateNotificationRecord(
3997                 mTestNotificationChannel, 1, "group", false);
3998         mService.addNotification(notification);
3999         mService.addNotification(notificationChild);
4000 
4001         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4002         when(mSnoozeHelper.canSnooze(2)).thenReturn(false);
4003 
4004         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4005                 mService.new SnoozeNotificationRunnable(
4006                         notificationChild.getKey(), 100, null);
4007         snoozeNotificationRunnable.run();
4008 
4009         verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
4010         assertThat(mService.getNotificationRecordCount()).isEqualTo(2);
4011     }
4012 
4013     @Test
testSnoozeRunnable_tooManySnoozed_summaryNotification()4014     public void testSnoozeRunnable_tooManySnoozed_summaryNotification() {
4015         final NotificationRecord notification = generateNotificationRecord(
4016                 mTestNotificationChannel, 1, "group", true);
4017         final NotificationRecord notificationChild = generateNotificationRecord(
4018                 mTestNotificationChannel, 12, "group", false);
4019         final NotificationRecord notificationChild2 = generateNotificationRecord(
4020                 mTestNotificationChannel, 13, "group", false);
4021         mService.addNotification(notification);
4022         mService.addNotification(notificationChild);
4023         mService.addNotification(notificationChild2);
4024 
4025         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4026         when(mSnoozeHelper.canSnooze(3)).thenReturn(false);
4027 
4028         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4029                 mService.new SnoozeNotificationRunnable(
4030                         notification.getKey(), 100, null);
4031         snoozeNotificationRunnable.run();
4032 
4033         verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
4034         assertThat(mService.getNotificationRecordCount()).isEqualTo(3);
4035     }
4036 
4037     @Test
testSnoozeRunnable_reSnoozeASingleSnoozedNotification()4038     public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() {
4039         final NotificationRecord notification = generateNotificationRecord(
4040                 mTestNotificationChannel, 1, null, true);
4041         mService.addNotification(notification);
4042         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
4043         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4044 
4045         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4046                 mService.new SnoozeNotificationRunnable(
4047                 notification.getKey(), 100, null);
4048         snoozeNotificationRunnable.run();
4049         snoozeNotificationRunnable.run();
4050 
4051         // snooze twice
4052         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
4053     }
4054 
4055     @Test
testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey()4056     public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() {
4057         final NotificationRecord notification = generateNotificationRecord(
4058                 mTestNotificationChannel, 1, "group", true);
4059         mService.addNotification(notification);
4060         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
4061         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4062 
4063         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4064                 mService.new SnoozeNotificationRunnable(
4065                 notification.getKey(), 100, null);
4066         snoozeNotificationRunnable.run();
4067         snoozeNotificationRunnable.run();
4068 
4069         // snooze twice
4070         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
4071     }
4072 
4073     @Test
testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey()4074     public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
4075         final NotificationRecord notification = generateNotificationRecord(
4076                 mTestNotificationChannel, 1, "group", true);
4077         final NotificationRecord notification2 = generateNotificationRecord(
4078                 mTestNotificationChannel, 2, "group", true);
4079         mService.addNotification(notification);
4080         mService.addNotification(notification2);
4081         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
4082         when(mSnoozeHelper.getNotifications(
4083                 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
4084         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4085 
4086         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4087                 mService.new SnoozeNotificationRunnable(
4088                         notification.getKey(), 100, null);
4089         snoozeNotificationRunnable.run();
4090         when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
4091                 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
4092         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
4093                 mService.new SnoozeNotificationRunnable(
4094                         notification2.getKey(), 100, null);
4095         snoozeNotificationRunnable2.run();
4096 
4097         // snooze twice
4098         verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
4099     }
4100 
4101     @Test
testSnoozeRunnable_snoozeNonGrouped()4102     public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
4103         final NotificationRecord nonGrouped = generateNotificationRecord(
4104                 mTestNotificationChannel, 1, null, false);
4105         final NotificationRecord grouped = generateNotificationRecord(
4106                 mTestNotificationChannel, 2, "group", false);
4107         mService.addNotification(grouped);
4108         mService.addNotification(nonGrouped);
4109         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4110 
4111         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4112                 mService.new SnoozeNotificationRunnable(
4113                         nonGrouped.getKey(), 100, null);
4114         snoozeNotificationRunnable.run();
4115 
4116         // only snooze the one notification
4117         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4118         assertTrue(nonGrouped.getStats().hasSnoozed());
4119 
4120         assertEquals(2, mNotificationRecordLogger.numCalls());
4121         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4122                 mNotificationRecordLogger.event(0));
4123         assertEquals(
4124                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4125                 mNotificationRecordLogger.event(1));
4126     }
4127 
4128     @Test
testSnoozeRunnable_snoozeSummary_withChildren()4129     public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
4130         final NotificationRecord parent = generateNotificationRecord(
4131                 mTestNotificationChannel, 1, "group", true);
4132         final NotificationRecord child = generateNotificationRecord(
4133                 mTestNotificationChannel, 2, "group", false);
4134         final NotificationRecord child2 = generateNotificationRecord(
4135                 mTestNotificationChannel, 3, "group", false);
4136         mService.addNotification(parent);
4137         mService.addNotification(child);
4138         mService.addNotification(child2);
4139         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4140 
4141         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4142                 mService.new SnoozeNotificationRunnable(
4143                         parent.getKey(), 100, null);
4144         snoozeNotificationRunnable.run();
4145 
4146         // snooze parent and children
4147         verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
4148     }
4149 
4150     @Test
testSnoozeRunnable_snoozeGroupChild_fellowChildren()4151     public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
4152         final NotificationRecord parent = generateNotificationRecord(
4153                 mTestNotificationChannel, 1, "group", true);
4154         final NotificationRecord child = generateNotificationRecord(
4155                 mTestNotificationChannel, 2, "group", false);
4156         final NotificationRecord child2 = generateNotificationRecord(
4157                 mTestNotificationChannel, 3, "group", false);
4158         mService.addNotification(parent);
4159         mService.addNotification(child);
4160         mService.addNotification(child2);
4161         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4162 
4163         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4164                 mService.new SnoozeNotificationRunnable(
4165                         child2.getKey(), 100, null);
4166         snoozeNotificationRunnable.run();
4167 
4168         // only snooze the one child
4169         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4170 
4171         assertEquals(2, mNotificationRecordLogger.numCalls());
4172         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4173                 mNotificationRecordLogger.event(0));
4174         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
4175                         .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
4176     }
4177 
4178     @Test
testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()4179     public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
4180         final NotificationRecord parent = generateNotificationRecord(
4181                 mTestNotificationChannel, 1, "group", true);
4182         assertTrue(parent.getSbn().getNotification().isGroupSummary());
4183         final NotificationRecord child = generateNotificationRecord(
4184                 mTestNotificationChannel, 2, "group", false);
4185         mService.addNotification(parent);
4186         mService.addNotification(child);
4187         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4188 
4189         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4190                 mService.new SnoozeNotificationRunnable(
4191                         child.getKey(), 100, null);
4192         snoozeNotificationRunnable.run();
4193 
4194         // snooze child and summary
4195         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
4196 
4197         assertEquals(4, mNotificationRecordLogger.numCalls());
4198         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4199                 mNotificationRecordLogger.event(0));
4200         assertEquals(
4201                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4202                 mNotificationRecordLogger.event(1));
4203         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4204                 mNotificationRecordLogger.event(2));
4205         assertEquals(
4206                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4207                 mNotificationRecordLogger.event(3));
4208     }
4209 
4210     @Test
testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()4211     public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
4212         final NotificationRecord child = generateNotificationRecord(
4213                 mTestNotificationChannel, 2, "group", false);
4214         mService.addNotification(child);
4215         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4216 
4217         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4218                 mService.new SnoozeNotificationRunnable(
4219                         child.getKey(), 100, null);
4220         snoozeNotificationRunnable.run();
4221 
4222         // snooze child only
4223         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4224 
4225         assertEquals(2, mNotificationRecordLogger.numCalls());
4226         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4227                 mNotificationRecordLogger.event(0));
4228         assertEquals(
4229                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4230                 mNotificationRecordLogger.event(1));
4231     }
4232 
4233     @Test
testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed()4234     public void testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed() throws Exception {
4235         final NotificationRecord parent = generateNotificationRecord(
4236                 mTestNotificationChannel, 1, GroupHelper.AUTOGROUP_KEY, true);
4237         final NotificationRecord child = generateNotificationRecord(
4238                 mTestNotificationChannel, 2, GroupHelper.AUTOGROUP_KEY, false);
4239         mService.addNotification(parent);
4240         mService.addNotification(child);
4241         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4242 
4243         // snooze child only
4244         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4245                 mService.new SnoozeNotificationRunnable(
4246                         child.getKey(), 100, null);
4247         snoozeNotificationRunnable.run();
4248 
4249         // only child should be snoozed
4250         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4251 
4252         // both group summary and child should be cancelled
4253         assertNull(mService.getNotificationRecord(parent.getKey()));
4254         assertNull(mService.getNotificationRecord(child.getKey()));
4255 
4256         assertEquals(4, mNotificationRecordLogger.numCalls());
4257         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4258                 mNotificationRecordLogger.event(0));
4259         assertEquals(
4260                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4261                 mNotificationRecordLogger.event(1));
4262     }
4263 
4264     @Test
testPostGroupChild_unsnoozeParent()4265     public void testPostGroupChild_unsnoozeParent() throws Exception {
4266         final NotificationRecord child = generateNotificationRecord(
4267                 mTestNotificationChannel, 2, "group", false);
4268 
4269         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
4270                 child.getSbn().getId(), child.getSbn().getNotification(),
4271                 child.getSbn().getUserId());
4272         waitForIdle();
4273 
4274         verify(mSnoozeHelper, times(1)).repostGroupSummary(
4275                 anyString(), anyInt(), eq(child.getGroupKey()));
4276     }
4277 
4278     @Test
testPostNonGroup_noUnsnoozing()4279     public void testPostNonGroup_noUnsnoozing() throws Exception {
4280         final NotificationRecord record = generateNotificationRecord(
4281                 mTestNotificationChannel, 2, null, false);
4282 
4283         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
4284                 record.getSbn().getId(), record.getSbn().getNotification(),
4285                 record.getSbn().getUserId());
4286         waitForIdle();
4287 
4288         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
4289     }
4290 
4291     @Test
testPostGroupSummary_noUnsnoozing()4292     public void testPostGroupSummary_noUnsnoozing() throws Exception {
4293         final NotificationRecord parent = generateNotificationRecord(
4294                 mTestNotificationChannel, 2, "group", true);
4295 
4296         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
4297                 parent.getSbn().getId(), parent.getSbn().getNotification(),
4298                 parent.getSbn().getUserId());
4299         waitForIdle();
4300 
4301         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
4302     }
4303 
4304     @Test
testSystemNotificationListenerCanUnsnooze()4305     public void testSystemNotificationListenerCanUnsnooze() throws Exception {
4306         final NotificationRecord nr = generateNotificationRecord(
4307                 mTestNotificationChannel, 2, "group", false);
4308 
4309         mBinderService.enqueueNotificationWithTag(PKG, PKG,
4310                 "testSystemNotificationListenerCanUnsnooze",
4311                 nr.getSbn().getId(), nr.getSbn().getNotification(),
4312                 nr.getSbn().getUserId());
4313         waitForIdle();
4314         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4315                 mService.new SnoozeNotificationRunnable(
4316                         nr.getKey(), 100, null);
4317         snoozeNotificationRunnable.run();
4318 
4319         ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
4320                 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0, 234);
4321         listener.isSystem = true;
4322         when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
4323 
4324         mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
4325         waitForIdle();
4326         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4327         assertEquals(1, notifs.length);
4328         assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
4329     }
4330 
4331     @Test
testSetListenerAccessForUser()4332     public void testSetListenerAccessForUser() throws Exception {
4333         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4334         ComponentName c = ComponentName.unflattenFromString("package/Component");
4335         mBinderService.setNotificationListenerAccessGrantedForUser(
4336                 c, user.getIdentifier(), true, true);
4337 
4338 
4339         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
4340         verify(mListeners, times(1)).setPackageOrComponentEnabled(
4341                 c.flattenToString(), user.getIdentifier(), true, true, true);
4342         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4343                 c.flattenToString(), user.getIdentifier(), false, true, true);
4344         verify(mAssistants, never()).setPackageOrComponentEnabled(
4345                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4346     }
4347 
4348     @Test
testSetListenerAccessForUser_grantWithNameTooLong_throws()4349     public void testSetListenerAccessForUser_grantWithNameTooLong_throws() {
4350         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4351         ComponentName c = new ComponentName("com.example.package",
4352                 com.google.common.base.Strings.repeat("Blah", 150));
4353 
4354         assertThrows(IllegalArgumentException.class,
4355                 () -> mBinderService.setNotificationListenerAccessGrantedForUser(
4356                         c, user.getIdentifier(), /* enabled= */ true, true));
4357     }
4358 
4359     @Test
testSetListenerAccessForUser_revokeWithNameTooLong_okay()4360     public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception {
4361         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4362         ComponentName c = new ComponentName("com.example.package",
4363                 com.google.common.base.Strings.repeat("Blah", 150));
4364 
4365         mBinderService.setNotificationListenerAccessGrantedForUser(
4366                 c, user.getIdentifier(), /* enabled= */ false, true);
4367 
4368         verify(mListeners).setPackageOrComponentEnabled(
4369                 c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true);
4370     }
4371 
4372     @Test
testSetAssistantAccessForUser()4373     public void testSetAssistantAccessForUser() throws Exception {
4374         UserInfo ui = new UserInfo();
4375         ui.id = mContext.getUserId() + 10;
4376         UserHandle user = UserHandle.of(ui.id);
4377         List<UserInfo> uis = new ArrayList<>();
4378         uis.add(ui);
4379         ComponentName c = ComponentName.unflattenFromString("package/Component");
4380         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4381 
4382         mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
4383 
4384         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
4385         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4386                 c.flattenToString(), user.getIdentifier(), true, true, true);
4387         verify(mAssistants).setUserSet(ui.id, true);
4388         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4389                 c.flattenToString(), user.getIdentifier(), false, true);
4390         verify(mListeners, never()).setPackageOrComponentEnabled(
4391                 any(), anyInt(), anyBoolean(), anyBoolean());
4392     }
4393 
4394     @Test
testGetAssistantAllowedForUser()4395     public void testGetAssistantAllowedForUser() throws Exception {
4396         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4397         try {
4398             mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
4399         } catch (IllegalStateException e) {
4400             if (!e.getMessage().contains("At most one NotificationAssistant")) {
4401                 throw e;
4402             }
4403         }
4404         verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
4405     }
4406 
4407     @Test
testGetAssistantAllowed()4408     public void testGetAssistantAllowed() throws Exception {
4409         try {
4410             mBinderService.getAllowedNotificationAssistant();
4411         } catch (IllegalStateException e) {
4412             if (!e.getMessage().contains("At most one NotificationAssistant")) {
4413                 throw e;
4414             }
4415         }
4416         verify(mAssistants, times(1)).getAllowedComponents(mContext.getUserId());
4417     }
4418 
4419     @Test
testSetNASMigrationDoneAndResetDefault_enableNAS()4420     public void testSetNASMigrationDoneAndResetDefault_enableNAS() throws Exception {
4421         int userId = 10;
4422         setNASMigrationDone(false, userId);
4423         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
4424 
4425         mBinderService.setNASMigrationDoneAndResetDefault(userId, true);
4426 
4427         assertTrue(mService.isNASMigrationDone(userId));
4428         verify(mAssistants, times(1)).resetDefaultFromConfig();
4429     }
4430 
4431     @Test
testSetNASMigrationDoneAndResetDefault_disableNAS()4432     public void testSetNASMigrationDoneAndResetDefault_disableNAS() throws Exception {
4433         int userId = 10;
4434         setNASMigrationDone(false, userId);
4435         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
4436 
4437         mBinderService.setNASMigrationDoneAndResetDefault(userId, false);
4438 
4439         assertTrue(mService.isNASMigrationDone(userId));
4440         verify(mAssistants, times(1)).clearDefaults();
4441     }
4442 
4443     @Test
testSetNASMigrationDoneAndResetDefault_multiProfile()4444     public void testSetNASMigrationDoneAndResetDefault_multiProfile() throws Exception {
4445         int userId1 = 11;
4446         int userId2 = 12; //work profile
4447         setNASMigrationDone(false, userId1);
4448         setNASMigrationDone(false, userId2);
4449         setUsers(new int[]{userId1, userId2});
4450         when(mUm.isManagedProfile(userId2)).thenReturn(true);
4451         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2});
4452 
4453         mBinderService.setNASMigrationDoneAndResetDefault(userId1, true);
4454         assertTrue(mService.isNASMigrationDone(userId1));
4455         assertTrue(mService.isNASMigrationDone(userId2));
4456     }
4457 
4458     @Test
testSetNASMigrationDoneAndResetDefault_multiUser()4459     public void testSetNASMigrationDoneAndResetDefault_multiUser() throws Exception {
4460         int userId1 = 11;
4461         int userId2 = 12;
4462         setNASMigrationDone(false, userId1);
4463         setNASMigrationDone(false, userId2);
4464         setUsers(new int[]{userId1, userId2});
4465         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1});
4466         when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2});
4467 
4468         mBinderService.setNASMigrationDoneAndResetDefault(userId1, true);
4469         assertTrue(mService.isNASMigrationDone(userId1));
4470         assertFalse(mService.isNASMigrationDone(userId2));
4471     }
4472 
4473     @Test
testSetDndAccessForUser()4474     public void testSetDndAccessForUser() throws Exception {
4475         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4476         ComponentName c = ComponentName.unflattenFromString("package/Component");
4477         mBinderService.setNotificationPolicyAccessGrantedForUser(
4478                 c.getPackageName(), user.getIdentifier(), true);
4479 
4480         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
4481         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4482                 c.getPackageName(), user.getIdentifier(), true, true);
4483         verify(mAssistants, never()).setPackageOrComponentEnabled(
4484                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4485         verify(mListeners, never()).setPackageOrComponentEnabled(
4486                 any(), anyInt(), anyBoolean(), anyBoolean());
4487     }
4488 
4489     @Test
testSetListenerAccess()4490     public void testSetListenerAccess() throws Exception {
4491         ComponentName c = ComponentName.unflattenFromString("package/Component");
4492         mBinderService.setNotificationListenerAccessGranted(c, true, true);
4493 
4494         verify(mListeners, times(1)).setPackageOrComponentEnabled(
4495                 c.flattenToString(), mContext.getUserId(), true, true, true);
4496         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4497                 c.flattenToString(), mContext.getUserId(), false, true, true);
4498         verify(mAssistants, never()).setPackageOrComponentEnabled(
4499                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4500     }
4501 
4502     @Test
testSetAssistantAccess()4503     public void testSetAssistantAccess() throws Exception {
4504         List<UserInfo> uis = new ArrayList<>();
4505         UserInfo ui = new UserInfo();
4506         ui.id = mContext.getUserId();
4507         uis.add(ui);
4508         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4509         ComponentName c = ComponentName.unflattenFromString("package/Component");
4510 
4511         mBinderService.setNotificationAssistantAccessGranted(c, true);
4512 
4513         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4514                 c.flattenToString(), ui.id, true, true, true);
4515         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4516                 c.flattenToString(), ui.id, false, true);
4517         verify(mListeners, never()).setPackageOrComponentEnabled(
4518                 any(), anyInt(), anyBoolean(), anyBoolean());
4519     }
4520 
4521     @Test
testSetAssistantAccess_multiProfile()4522     public void testSetAssistantAccess_multiProfile() throws Exception {
4523         List<UserInfo> uis = new ArrayList<>();
4524         UserInfo ui = new UserInfo();
4525         ui.id = mContext.getUserId();
4526         uis.add(ui);
4527         UserInfo ui10 = new UserInfo();
4528         ui10.id = mContext.getUserId() + 10;
4529         uis.add(ui10);
4530         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4531         ComponentName c = ComponentName.unflattenFromString("package/Component");
4532 
4533         mBinderService.setNotificationAssistantAccessGranted(c, true);
4534 
4535         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4536                 c.flattenToString(), ui.id, true, true, true);
4537         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4538                 c.flattenToString(), ui10.id, true, true, true);
4539 
4540         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4541                 c.flattenToString(), ui.id, false, true);
4542         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4543                 c.flattenToString(), ui10.id, false, true);
4544         verify(mListeners, never()).setPackageOrComponentEnabled(
4545                 any(), anyInt(), anyBoolean(), anyBoolean());
4546     }
4547 
4548     @Test
testSetAssistantAccess_nullWithAllowedAssistant()4549     public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
4550         ArrayList<ComponentName> componentList = new ArrayList<>();
4551         ComponentName c = ComponentName.unflattenFromString("package/Component");
4552         componentList.add(c);
4553         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
4554         List<UserInfo> uis = new ArrayList<>();
4555         UserInfo ui = new UserInfo();
4556         ui.id = mContext.getUserId();
4557         uis.add(ui);
4558         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4559 
4560         mBinderService.setNotificationAssistantAccessGranted(null, true);
4561 
4562         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4563                 c.flattenToString(), ui.id, true, false, true);
4564         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4565                 c.flattenToString(), ui.id, false,  false);
4566         verify(mListeners, never()).setPackageOrComponentEnabled(
4567                 any(), anyInt(), anyBoolean(), anyBoolean());
4568     }
4569 
4570     @Test
testSetAssistantAccessForUser_nullWithAllowedAssistant()4571     public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
4572         List<UserInfo> uis = new ArrayList<>();
4573         UserInfo ui = new UserInfo();
4574         ui.id = mContext.getUserId() + 10;
4575         uis.add(ui);
4576         UserHandle user = ui.getUserHandle();
4577         ArrayList<ComponentName> componentList = new ArrayList<>();
4578         ComponentName c = ComponentName.unflattenFromString("package/Component");
4579         componentList.add(c);
4580         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
4581         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4582 
4583         mBinderService.setNotificationAssistantAccessGrantedForUser(
4584                 null, user.getIdentifier(), true);
4585 
4586         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4587                 c.flattenToString(), user.getIdentifier(), true, false, true);
4588         verify(mAssistants).setUserSet(ui.id, true);
4589         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4590                 c.flattenToString(), user.getIdentifier(), false,  false);
4591         verify(mListeners, never()).setPackageOrComponentEnabled(
4592                 any(), anyInt(), anyBoolean(), anyBoolean());
4593     }
4594 
4595     @Test
testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()4596     public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
4597             throws Exception {
4598         List<UserInfo> uis = new ArrayList<>();
4599         UserInfo ui = new UserInfo();
4600         ui.id = mContext.getUserId();
4601         uis.add(ui);
4602         UserInfo ui10 = new UserInfo();
4603         ui10.id = mContext.getUserId() + 10;
4604         uis.add(ui10);
4605         UserHandle user = ui.getUserHandle();
4606         ArrayList<ComponentName> componentList = new ArrayList<>();
4607         ComponentName c = ComponentName.unflattenFromString("package/Component");
4608         componentList.add(c);
4609         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
4610         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4611 
4612         mBinderService.setNotificationAssistantAccessGrantedForUser(
4613                     null, user.getIdentifier(), true);
4614 
4615         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4616                 c.flattenToString(), user.getIdentifier(), true, false, true);
4617         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4618                 c.flattenToString(), ui10.id, true, false, true);
4619         verify(mAssistants).setUserSet(ui.id, true);
4620         verify(mAssistants).setUserSet(ui10.id, true);
4621         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4622                 c.flattenToString(), user.getIdentifier(), false,  false);
4623         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4624                 c.flattenToString(), ui10.id, false,  false);
4625         verify(mListeners, never()).setPackageOrComponentEnabled(
4626                 any(), anyInt(), anyBoolean(), anyBoolean());
4627     }
4628 
4629     @Test
testSetDndAccess()4630     public void testSetDndAccess() throws Exception {
4631         ComponentName c = ComponentName.unflattenFromString("package/Component");
4632 
4633         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
4634 
4635         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4636                 c.getPackageName(), mContext.getUserId(), true, true);
4637         verify(mAssistants, never()).setPackageOrComponentEnabled(
4638                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4639         verify(mListeners, never()).setPackageOrComponentEnabled(
4640                 any(), anyInt(), anyBoolean(), anyBoolean());
4641     }
4642 
4643     @Test
testSetListenerAccess_onLowRam()4644     public void testSetListenerAccess_onLowRam() throws Exception {
4645         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4646         ComponentName c = ComponentName.unflattenFromString("package/Component");
4647         mBinderService.setNotificationListenerAccessGranted(c, true, true);
4648 
4649         verify(mListeners).setPackageOrComponentEnabled(
4650                 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4651         verify(mConditionProviders).setPackageOrComponentEnabled(
4652                 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4653         verify(mAssistants).migrateToXml();
4654         verify(mAssistants).resetDefaultAssistantsIfNecessary();
4655     }
4656 
4657     @Test
testSetAssistantAccess_onLowRam()4658     public void testSetAssistantAccess_onLowRam() throws Exception {
4659         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4660         ComponentName c = ComponentName.unflattenFromString("package/Component");
4661         List<UserInfo> uis = new ArrayList<>();
4662         UserInfo ui = new UserInfo();
4663         ui.id = mContext.getUserId();
4664         uis.add(ui);
4665         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4666 
4667         mBinderService.setNotificationAssistantAccessGranted(c, true);
4668 
4669         verify(mListeners).migrateToXml();
4670         verify(mConditionProviders).setPackageOrComponentEnabled(
4671                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4672         verify(mAssistants).migrateToXml();
4673         verify(mAssistants).resetDefaultAssistantsIfNecessary();
4674     }
4675 
4676     @Test
testSetDndAccess_onLowRam()4677     public void testSetDndAccess_onLowRam() throws Exception {
4678         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4679         ComponentName c = ComponentName.unflattenFromString("package/Component");
4680         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
4681 
4682         verify(mListeners).migrateToXml();
4683         verify(mConditionProviders).setPackageOrComponentEnabled(
4684                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4685         verify(mAssistants).migrateToXml();
4686         verify(mAssistants).resetDefaultAssistantsIfNecessary();
4687     }
4688 
4689     @Test
testSetListenerAccess_doesNothingOnLowRam_exceptWatch()4690     public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
4691         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4692         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4693         ComponentName c = ComponentName.unflattenFromString("package/Component");
4694 
4695         mBinderService.setNotificationListenerAccessGranted(c, true, true);
4696 
4697         verify(mListeners, times(1)).setPackageOrComponentEnabled(
4698                 c.flattenToString(), mContext.getUserId(), true, true, true);
4699         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4700                 c.flattenToString(), mContext.getUserId(), false, true, true);
4701         verify(mAssistants, never()).setPackageOrComponentEnabled(
4702                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4703     }
4704 
4705     @Test
testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()4706     public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
4707         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4708         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4709         ComponentName c = ComponentName.unflattenFromString("package/Component");
4710         List<UserInfo> uis = new ArrayList<>();
4711         UserInfo ui = new UserInfo();
4712         ui.id = mContext.getUserId();
4713         uis.add(ui);
4714         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4715 
4716         mBinderService.setNotificationAssistantAccessGranted(c, true);
4717 
4718         verify(mListeners, never()).setPackageOrComponentEnabled(
4719                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4720         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4721                 c.flattenToString(), ui.id, false, true);
4722         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4723                 c.flattenToString(), ui.id, true, true, true);
4724     }
4725 
4726     @Test
testSetDndAccess_doesNothingOnLowRam_exceptWatch()4727     public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
4728         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4729         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4730         ComponentName c = ComponentName.unflattenFromString("package/Component");
4731 
4732         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
4733 
4734         verify(mListeners, never()).setPackageOrComponentEnabled(
4735                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4736         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4737                 c.getPackageName(), mContext.getUserId(), true, true);
4738         verify(mAssistants, never()).setPackageOrComponentEnabled(
4739                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4740     }
4741 
4742     @Test
testOnlyAutogroupIfNeeded_newNotification_ghUpdate()4743     public void testOnlyAutogroupIfNeeded_newNotification_ghUpdate() {
4744         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
4745         mService.addEnqueuedNotification(r);
4746         NotificationManagerService.PostNotificationRunnable runnable =
4747                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
4748                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4749         runnable.run();
4750         waitForIdle();
4751 
4752         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
4753     }
4754 
4755     @Test
testOnlyAutogroupIfNeeded_groupChanged_ghUpdate()4756     public void testOnlyAutogroupIfNeeded_groupChanged_ghUpdate() {
4757         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0,
4758                 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", "group", false);
4759         mService.addNotification(r);
4760 
4761         NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0,
4762                 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", null, false);
4763         mService.addEnqueuedNotification(update);
4764         NotificationManagerService.PostNotificationRunnable runnable =
4765                 mService.new PostNotificationRunnable(update.getKey(),
4766                         update.getSbn().getPackageName(), update.getUid(),
4767                         mPostNotificationTrackerFactory.newTracker(null));
4768         runnable.run();
4769         waitForIdle();
4770 
4771         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
4772     }
4773 
4774     @Test
testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate()4775     public void testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate() {
4776         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0,
4777                 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", "group", false);
4778         mService.addNotification(r);
4779 
4780         NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0,
4781                 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", null, false);
4782         update.getNotification().flags = FLAG_AUTO_CANCEL;
4783         mService.addEnqueuedNotification(update);
4784         NotificationManagerService.PostNotificationRunnable runnable =
4785                 mService.new PostNotificationRunnable(update.getKey(),
4786                         update.getSbn().getPackageName(), update.getUid(),
4787                         mPostNotificationTrackerFactory.newTracker(null));
4788         runnable.run();
4789         waitForIdle();
4790 
4791         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
4792     }
4793 
4794     @Test
testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate()4795     public void testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate() {
4796         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0,
4797                 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false);
4798         mService.addNotification(r);
4799         NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0,
4800                 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false);
4801         update.getNotification().color = Color.BLACK;
4802         mService.addEnqueuedNotification(update);
4803 
4804         NotificationManagerService.PostNotificationRunnable runnable =
4805                 mService.new PostNotificationRunnable(update.getKey(),
4806                         update.getSbn().getPackageName(),
4807                         update.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4808         runnable.run();
4809         waitForIdle();
4810 
4811         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
4812     }
4813 
4814     @Test
testDontAutogroupIfCritical()4815     public void testDontAutogroupIfCritical() throws Exception {
4816         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
4817         r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
4818         mService.addEnqueuedNotification(r);
4819         NotificationManagerService.PostNotificationRunnable runnable =
4820                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
4821                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4822         runnable.run();
4823 
4824         r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
4825         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
4826         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
4827                 r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4828         mService.addEnqueuedNotification(r);
4829 
4830         runnable.run();
4831         waitForIdle();
4832 
4833         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
4834     }
4835 
4836     @Test
testNoNotificationDuringSetupPermission()4837     public void testNoNotificationDuringSetupPermission() throws Exception {
4838         mContext.getTestablePermissions().setPermission(
4839                 android.Manifest.permission.NOTIFICATION_DURING_SETUP, PERMISSION_GRANTED);
4840         Bundle extras = new Bundle();
4841         extras.putBoolean(EXTRA_ALLOW_DURING_SETUP, true);
4842         Notification.Builder nb = new Notification.Builder(mContext,
4843                 mTestNotificationChannel.getId())
4844                 .setContentTitle("foo")
4845                 .addExtras(extras)
4846                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4847         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4848                 "testNoNotificationDuringSetupPermission", mUid, 0,
4849                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4850         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4851 
4852         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4853                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4854         waitForIdle();
4855 
4856         NotificationRecord posted = mService.findNotificationLocked(
4857                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4858 
4859         assertTrue(posted.getNotification().extras.containsKey(EXTRA_ALLOW_DURING_SETUP));
4860     }
4861 
4862     @Test
testNoFakeColorizedPermission()4863     public void testNoFakeColorizedPermission() throws Exception {
4864         mContext.getTestablePermissions().setPermission(
4865                 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_DENIED);
4866         Notification.Builder nb = new Notification.Builder(mContext,
4867                 mTestNotificationChannel.getId())
4868                 .setContentTitle("foo")
4869                 .setColorized(true).setColor(Color.WHITE)
4870                 .setFlag(FLAG_CAN_COLORIZE, true)
4871                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4872         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4873                 "testNoFakeColorizedPermission", mUid, 0,
4874                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4875         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4876 
4877         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4878                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4879         waitForIdle();
4880 
4881         NotificationRecord posted = mService.findNotificationLocked(
4882                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4883 
4884         assertFalse(posted.getNotification().isColorized());
4885     }
4886 
4887     @Test
testMediaStyleRemote_hasPermission()4888     public void testMediaStyleRemote_hasPermission() throws RemoteException {
4889         String deviceName = "device";
4890         mContext.getTestablePermissions().setPermission(
4891                 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_GRANTED);
4892         Notification.MediaStyle style = new Notification.MediaStyle();
4893         style.setRemotePlaybackInfo(deviceName, 0, null);
4894         Notification.Builder nb = new Notification.Builder(mContext,
4895                 mTestNotificationChannel.getId())
4896                 .setStyle(style);
4897 
4898         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4899                 "testMediaStyleRemoteHasPermission", mUid, 0,
4900                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4901         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4902 
4903         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4904                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4905         waitForIdle();
4906 
4907         NotificationRecord posted = mService.findNotificationLocked(
4908                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4909         Bundle extras = posted.getNotification().extras;
4910 
4911         assertTrue(extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4912         assertEquals(deviceName, extras.getString(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4913     }
4914 
4915     @Test
testMediaStyleRemote_noPermission()4916     public void testMediaStyleRemote_noPermission() throws RemoteException {
4917         String deviceName = "device";
4918         mContext.getTestablePermissions().setPermission(
4919                 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_DENIED);
4920         Notification.MediaStyle style = new Notification.MediaStyle();
4921         style.setRemotePlaybackInfo(deviceName, 0, null);
4922         Notification.Builder nb = new Notification.Builder(mContext,
4923                 mTestNotificationChannel.getId())
4924                 .setStyle(style);
4925 
4926         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4927                 "testMediaStyleRemoteNoPermission", mUid, 0,
4928                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4929         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4930 
4931         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4932                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4933         waitForIdle();
4934 
4935         NotificationRecord posted = mService.findNotificationLocked(
4936                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4937 
4938         assertFalse(posted.getNotification().extras
4939                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4940         assertFalse(posted.getNotification().extras
4941                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON));
4942         assertFalse(posted.getNotification().extras
4943                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT));
4944     }
4945 
4946     @Test
testCustomMediaStyleRemote_noPermission()4947     public void testCustomMediaStyleRemote_noPermission() throws RemoteException {
4948         String deviceName = "device";
4949         when(mPackageManager.checkPermission(
4950                 eq(android.Manifest.permission.MEDIA_CONTENT_CONTROL), any(), anyInt()))
4951                 .thenReturn(PERMISSION_DENIED);
4952         Notification.DecoratedMediaCustomViewStyle style =
4953                 new Notification.DecoratedMediaCustomViewStyle();
4954         style.setRemotePlaybackInfo(deviceName, 0, null);
4955         Notification.Builder nb = new Notification.Builder(mContext,
4956                 mTestNotificationChannel.getId())
4957                 .setStyle(style);
4958 
4959         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4960                 "testCustomMediaStyleRemoteNoPermission", mUid, 0,
4961                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4962         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4963 
4964         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4965                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4966         waitForIdle();
4967 
4968         NotificationRecord posted = mService.findNotificationLocked(
4969                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4970 
4971         assertFalse(posted.getNotification().extras
4972                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4973         assertFalse(posted.getNotification().extras
4974                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON));
4975         assertFalse(posted.getNotification().extras
4976                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT));
4977     }
4978 
4979     @Test
testSubstituteAppName_hasPermission()4980     public void testSubstituteAppName_hasPermission() throws RemoteException {
4981         String subName = "Substitute Name";
4982         mContext.getTestablePermissions().setPermission(
4983                 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_GRANTED);
4984         Bundle extras = new Bundle();
4985         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, subName);
4986         Notification.Builder nb = new Notification.Builder(mContext,
4987                 mTestNotificationChannel.getId())
4988                 .addExtras(extras);
4989         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4990                 "testSubstituteAppNamePermission", mUid, 0,
4991                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4992         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4993 
4994         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4995                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4996         waitForIdle();
4997         NotificationRecord posted = mService.findNotificationLocked(
4998                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4999 
5000         assertTrue(posted.getNotification().extras
5001                 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
5002         assertEquals(posted.getNotification().extras
5003                 .getString(Notification.EXTRA_SUBSTITUTE_APP_NAME), subName);
5004     }
5005 
5006     @Test
testSubstituteAppName_noPermission()5007     public void testSubstituteAppName_noPermission() throws RemoteException {
5008         mContext.getTestablePermissions().setPermission(
5009                 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_DENIED);
5010         Bundle extras = new Bundle();
5011         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Substitute Name");
5012         Notification.Builder nb = new Notification.Builder(mContext,
5013                 mTestNotificationChannel.getId())
5014                 .addExtras(extras);
5015         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5016                 "testSubstituteAppNamePermission", mUid, 0,
5017                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
5018         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5019 
5020         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
5021                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5022         waitForIdle();
5023         NotificationRecord posted = mService.findNotificationLocked(
5024                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
5025 
5026         assertFalse(posted.getNotification().extras
5027                 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
5028     }
5029 
5030     @Test
testGetNotificationCountLocked()5031     public void testGetNotificationCountLocked() {
5032         String sampleTagToExclude = null;
5033         int sampleIdToExclude = 0;
5034         for (int i = 0; i < 20; i++) {
5035             NotificationRecord r =
5036                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
5037             mService.addEnqueuedNotification(r);
5038 
5039         }
5040         for (int i = 0; i < 20; i++) {
5041             NotificationRecord r =
5042                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
5043             mService.addNotification(r);
5044             sampleTagToExclude = r.getSbn().getTag();
5045             sampleIdToExclude = i;
5046         }
5047 
5048         // another package
5049         Notification n =
5050                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
5051                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5052                 .build();
5053 
5054         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
5055                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
5056         NotificationRecord otherPackage =
5057                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5058         mService.addEnqueuedNotification(otherPackage);
5059         mService.addNotification(otherPackage);
5060 
5061         // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
5062         // anything that's currently enqueued or posted
5063         int userId = mUserId;
5064         assertEquals(40,
5065                 mService.getNotificationCount(PKG, userId, 0, null));
5066         assertEquals(40,
5067                 mService.getNotificationCount(PKG, userId, 0, "tag2"));
5068 
5069         // return all for package "a" - "banana" tag isn't used
5070         assertEquals(2,
5071                 mService.getNotificationCount("a", userId, 0, "banana"));
5072 
5073         // exclude a known notification - it's excluded from only the posted list, not enqueued
5074         assertEquals(39, mService.getNotificationCount(
5075                 PKG, userId, sampleIdToExclude, sampleTagToExclude));
5076     }
5077 
5078     @Test
testAddAutogroup_requestsSort()5079     public void testAddAutogroup_requestsSort() throws Exception {
5080         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5081         mService.addNotification(r);
5082         mService.addAutogroupKeyLocked(r.getKey());
5083 
5084         verify(mRankingHandler, times(1)).requestSort();
5085     }
5086 
5087     @Test
testRemoveAutogroup_requestsSort()5088     public void testRemoveAutogroup_requestsSort() throws Exception {
5089         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5090         r.setOverrideGroupKey("TEST");
5091         mService.addNotification(r);
5092         mService.removeAutogroupKeyLocked(r.getKey());
5093 
5094         verify(mRankingHandler, times(1)).requestSort();
5095     }
5096 
5097     @Test
testReaddAutogroup_noSort()5098     public void testReaddAutogroup_noSort() throws Exception {
5099         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5100         r.setOverrideGroupKey("TEST");
5101         mService.addNotification(r);
5102         mService.addAutogroupKeyLocked(r.getKey());
5103 
5104         verify(mRankingHandler, never()).requestSort();
5105     }
5106 
5107     @Test
testHandleRankingSort_sendsUpdateOnSignalExtractorChange()5108     public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
5109         mService.setPreferencesHelper(mPreferencesHelper);
5110         NotificationManagerService.WorkerHandler handler = mock(
5111                 NotificationManagerService.WorkerHandler.class);
5112         mService.setHandler(handler);
5113 
5114         Map<String, Answer> answers = getSignalExtractorSideEffects();
5115         for (String message : answers.keySet()) {
5116             mService.clearNotifications();
5117             final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5118             mService.addNotification(r);
5119 
5120             doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
5121 
5122             mService.handleRankingSort();
5123         }
5124         verify(handler, times(answers.size())).scheduleSendRankingUpdate();
5125     }
5126 
5127     @Test
testHandleRankingSort_noUpdateWhenNoSignalChange()5128     public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
5129         mService.setRankingHelper(mRankingHelper);
5130         NotificationManagerService.WorkerHandler handler = mock(
5131                 NotificationManagerService.WorkerHandler.class);
5132         mService.setHandler(handler);
5133 
5134         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5135         mService.addNotification(r);
5136 
5137         mService.handleRankingSort();
5138         verify(handler, never()).scheduleSendRankingUpdate();
5139     }
5140 
5141     @Test
testReadPolicyXml_readApprovedServicesFromXml()5142     public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
5143         final String upgradeXml = "<notification-policy version=\"1\">"
5144                 + "<ranking></ranking>"
5145                 + "<enabled_listeners>"
5146                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
5147                 + "</enabled_listeners>"
5148                 + "<enabled_assistants>"
5149                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
5150                 + "</enabled_assistants>"
5151                 + "<dnd_apps>"
5152                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
5153                 + "</dnd_apps>"
5154                 + "</notification-policy>";
5155         mService.readPolicyXml(
5156                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
5157                 false,
5158                 UserHandle.USER_ALL);
5159         verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
5160         verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
5161         verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
5162 
5163         // numbers are inflated for setup
5164         verify(mListeners, times(1)).migrateToXml();
5165         verify(mConditionProviders, times(1)).migrateToXml();
5166         verify(mAssistants, times(1)).migrateToXml();
5167         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
5168     }
5169 
5170     @Test
testReadPolicyXml_readSnoozedNotificationsFromXml()5171     public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
5172         final String upgradeXml = "<notification-policy version=\"1\">"
5173                 + "<snoozed-notifications>></snoozed-notifications>"
5174                 + "</notification-policy>";
5175         mService.readPolicyXml(
5176                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
5177                 false,
5178                 UserHandle.USER_ALL);
5179         verify(mSnoozeHelper, times(1)).readXml(any(TypedXmlPullParser.class), anyLong());
5180     }
5181 
5182     @Test
testReadPolicyXml_readApprovedServicesFromSettings()5183     public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
5184         final String preupgradeXml = "<notification-policy version=\"1\">"
5185                 + "<ranking></ranking>"
5186                 + "</notification-policy>";
5187         mService.readPolicyXml(
5188                 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
5189                 false,
5190                 UserHandle.USER_ALL);
5191         verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
5192         verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
5193         verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
5194 
5195         // numbers are inflated for setup
5196         verify(mListeners, times(2)).migrateToXml();
5197         verify(mConditionProviders, times(2)).migrateToXml();
5198         verify(mAssistants, times(2)).migrateToXml();
5199         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
5200     }
5201 
5202     @Test
testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser()5203     public void testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser() throws Exception {
5204         final String policyXml = "<notification-policy version=\"1\">"
5205                 + "<ranking></ranking>"
5206                 + "<enabled_listeners>"
5207                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5208                 + "</enabled_listeners>"
5209                 + "<enabled_assistants>"
5210                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5211                 + "</enabled_assistants>"
5212                 + "<dnd_apps>"
5213                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5214                 + "</dnd_apps>"
5215                 + "</notification-policy>";
5216         UserInfo ui = new UserInfo();
5217         ui.id = 10;
5218         ui.userType = USER_TYPE_PROFILE_CLONE;
5219         when(mUmInternal.getUserInfo(10)).thenReturn(ui);
5220         mService.readPolicyXml(
5221                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
5222                 true,
5223                 10);
5224         verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
5225         verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
5226         verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
5227     }
5228 
5229     @Test
testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()5230     public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
5231         final String policyXml = "<notification-policy version=\"1\">"
5232                 + "<ranking></ranking>"
5233                 + "<enabled_listeners>"
5234                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5235                 + "</enabled_listeners>"
5236                 + "<enabled_assistants>"
5237                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5238                 + "</enabled_assistants>"
5239                 + "<dnd_apps>"
5240                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5241                 + "</dnd_apps>"
5242                 + "</notification-policy>";
5243         UserInfo ui = new UserInfo();
5244         ui.id = 10;
5245         ui.userType = USER_TYPE_PROFILE_MANAGED;
5246         when(mUmInternal.getUserInfo(10)).thenReturn(ui);
5247         mService.readPolicyXml(
5248                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
5249                 true,
5250                 10);
5251         verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
5252         verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
5253         verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
5254     }
5255 
5256     @Test
testReadPolicyXml_restoresManagedServicesForNonManagedUser()5257     public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
5258         final String policyXml = "<notification-policy version=\"1\">"
5259                 + "<ranking></ranking>"
5260                 + "<enabled_listeners>"
5261                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5262                 + "</enabled_listeners>"
5263                 + "<enabled_assistants>"
5264                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5265                 + "</enabled_assistants>"
5266                 + "<dnd_apps>"
5267                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5268                 + "</dnd_apps>"
5269                 + "</notification-policy>";
5270         UserInfo ui = new UserInfo();
5271         ui.id = 10;
5272         ui.userType = USER_TYPE_FULL_SECONDARY;
5273         when(mUmInternal.getUserInfo(10)).thenReturn(ui);
5274         mService.readPolicyXml(
5275                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
5276                 true,
5277                 10);
5278         verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
5279         verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
5280         verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
5281     }
5282 
5283     @Test
testLocaleChangedCallsUpdateDefaultZenModeRules()5284     public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
5285         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
5286         mService.mZenModeHelper = mZenModeHelper;
5287         mService.mLocaleChangeReceiver.onReceive(mContext,
5288                 new Intent(Intent.ACTION_LOCALE_CHANGED));
5289 
5290         verify(mZenModeHelper, times(1)).updateDefaultZenRules(
5291                 anyInt(), anyBoolean());
5292     }
5293 
5294     @Test
testBumpFGImportance_channelChangePreOApp()5295     public void testBumpFGImportance_channelChangePreOApp() throws Exception {
5296         String preOPkg = PKG_N_MR1;
5297         final ApplicationInfo legacy = new ApplicationInfo();
5298         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
5299         when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
5300                 .thenReturn(legacy);
5301         when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
5302                 .thenReturn(Binder.getCallingUid());
5303         getContext().setMockPackageManager(mPackageManagerClient);
5304 
5305         Notification.Builder nb = new Notification.Builder(mContext,
5306                 NotificationChannel.DEFAULT_CHANNEL_ID)
5307                 .setContentTitle("foo")
5308                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5309                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
5310                 .setPriority(Notification.PRIORITY_MIN);
5311 
5312         StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
5313                 "testBumpFGImportance_channelChangePreOApp",
5314                 Binder.getCallingUid(), 0, nb.build(),
5315                 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
5316 
5317         mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
5318                 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
5319         waitForIdle();
5320 
5321         assertEquals(IMPORTANCE_LOW,
5322                 mService.getNotificationRecord(sbn.getKey()).getImportance());
5323         assertEquals(IMPORTANCE_DEFAULT, mBinderService.getPackageImportance(
5324                 sbn.getPackageName()));
5325 
5326         nb = new Notification.Builder(mContext)
5327                 .setContentTitle("foo")
5328                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5329                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
5330                 .setPriority(Notification.PRIORITY_MIN);
5331 
5332         sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
5333                 "testBumpFGImportance_channelChangePreOApp", Binder.getCallingUid(),
5334                 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
5335 
5336         mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
5337                 "testBumpFGImportance_channelChangePreOApp",
5338                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
5339         waitForIdle();
5340         assertEquals(IMPORTANCE_LOW,
5341                 mService.getNotificationRecord(sbn.getKey()).getImportance());
5342 
5343         NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
5344                 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
5345         assertEquals(IMPORTANCE_LOW, defaultChannel.getImportance());
5346     }
5347 
5348     @Test
testStats_updatedOnDirectReply()5349     public void testStats_updatedOnDirectReply() throws Exception {
5350         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5351         mService.addNotification(r);
5352 
5353         mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
5354         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
5355         verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r));
5356 
5357         assertEquals(1, mNotificationRecordLogger.numCalls());
5358         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
5359                 mNotificationRecordLogger.event(0));
5360     }
5361 
5362     @Test
testStats_updatedOnUserExpansion()5363     public void testStats_updatedOnUserExpansion() throws Exception {
5364         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5365         mService.addNotification(r);
5366 
5367         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
5368                 NOTIFICATION_LOCATION_UNKNOWN);
5369         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()),
5370                 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((true)));
5371         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5372 
5373         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
5374                 NOTIFICATION_LOCATION_UNKNOWN);
5375         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()),
5376                 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((false)));
5377         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5378 
5379         assertEquals(2, mNotificationRecordLogger.numCalls());
5380         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
5381                 mNotificationRecordLogger.event(0));
5382         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
5383                 mNotificationRecordLogger.event(1));
5384     }
5385 
5386     @Test
testStats_notUpdatedOnAutoExpansion()5387     public void testStats_notUpdatedOnAutoExpansion() throws Exception {
5388         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5389         mService.addNotification(r);
5390 
5391         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5392                 NOTIFICATION_LOCATION_UNKNOWN);
5393         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5394         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()),
5395                 eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((true)));
5396 
5397         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
5398                 NOTIFICATION_LOCATION_UNKNOWN);
5399         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5400         verify(mAssistants).notifyAssistantExpansionChangedLocked(
5401                 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((false)));
5402     }
5403 
5404     @Test
testStats_updatedOnViewSettings()5405     public void testStats_updatedOnViewSettings() throws Exception {
5406         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5407         mService.addNotification(r);
5408 
5409         mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
5410         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
5411     }
5412 
5413     @Test
testStats_updatedOnVisibilityChanged()5414     public void testStats_updatedOnVisibilityChanged() throws Exception {
5415         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5416         mService.addNotification(r);
5417 
5418         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
5419         mService.mNotificationDelegate.onNotificationVisibilityChanged(
5420                 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
5421         verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(true));
5422         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
5423         mService.mNotificationDelegate.onNotificationVisibilityChanged(
5424                 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
5425         verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(false));
5426         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
5427     }
5428 
5429     @Test
testStats_dismissalSurface()5430     public void testStats_dismissalSurface() throws Exception {
5431         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5432         r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5433         mService.addNotification(r);
5434 
5435         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
5436         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
5437                 r.getKey(), NotificationStats.DISMISSAL_AOD,
5438                 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
5439         waitForIdle();
5440 
5441         assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
5442 
5443         // Using mService.addNotification() does not generate a NotificationRecordLogger log,
5444         // so we only get the cancel notification.
5445         assertEquals(1, mNotificationRecordLogger.numCalls());
5446 
5447         assertEquals(
5448                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
5449                 mNotificationRecordLogger.event(0));
5450         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
5451     }
5452 
5453     @Test
testStats_dismissalSentiment()5454     public void testStats_dismissalSentiment() throws Exception {
5455         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5456         mService.addNotification(r);
5457 
5458         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
5459         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
5460                 r.getKey(), NotificationStats.DISMISSAL_AOD,
5461                 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
5462         waitForIdle();
5463 
5464         assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
5465                 r.getStats().getDismissalSentiment());
5466     }
5467 
5468     @Test
testTextChangedSet_forNewNotifs()5469     public void testTextChangedSet_forNewNotifs() throws Exception {
5470         NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
5471         mService.addEnqueuedNotification(original);
5472 
5473         NotificationManagerService.PostNotificationRunnable runnable =
5474                 mService.new PostNotificationRunnable(original.getKey(),
5475                         original.getSbn().getPackageName(),
5476                         original.getUid(),
5477                         mPostNotificationTrackerFactory.newTracker(null));
5478         runnable.run();
5479         waitForIdle();
5480 
5481         assertTrue(original.isTextChanged());
5482     }
5483 
5484     @Test
testVisuallyInterruptive_notSeen()5485     public void testVisuallyInterruptive_notSeen() throws Exception {
5486         NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
5487         mService.addNotification(original);
5488 
5489         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, original.getSbn().getId(),
5490                 original.getSbn().getTag(), mUid, 0,
5491                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
5492                         .setContentTitle("new title").build(),
5493                 UserHandle.getUserHandleForUid(mUid), null, 0);
5494         NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5495         mService.addEnqueuedNotification(update);
5496 
5497         NotificationManagerService.PostNotificationRunnable runnable =
5498                 mService.new PostNotificationRunnable(update.getKey(),
5499                         update.getSbn().getPackageName(),
5500                         update.getUid(),
5501                         mPostNotificationTrackerFactory.newTracker(null));
5502         runnable.run();
5503         waitForIdle();
5504 
5505         assertFalse(update.isInterruptive());
5506     }
5507 
5508     @Test
testApplyAdjustmentMultiUser()5509     public void testApplyAdjustmentMultiUser() throws Exception {
5510         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5511         mService.addNotification(r);
5512         NotificationManagerService.WorkerHandler handler = mock(
5513                 NotificationManagerService.WorkerHandler.class);
5514         mService.setHandler(handler);
5515 
5516         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
5517 
5518         Bundle signals = new Bundle();
5519         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5520                 USER_SENTIMENT_NEGATIVE);
5521         Adjustment adjustment = new Adjustment(
5522                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5523         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5524 
5525         waitForIdle();
5526 
5527         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
5528     }
5529 
5530     @Test
testAssistantBlockingTriggersCancel()5531     public void testAssistantBlockingTriggersCancel() throws Exception {
5532         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5533         mService.addNotification(r);
5534         NotificationManagerService.WorkerHandler handler = mock(
5535                 NotificationManagerService.WorkerHandler.class);
5536         mService.setHandler(handler);
5537 
5538         Bundle signals = new Bundle();
5539         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
5540         Adjustment adjustment = new Adjustment(
5541                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5542         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
5543         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5544 
5545         waitForIdle();
5546 
5547         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
5548         verify(handler, times(1)).scheduleCancelNotification(any());
5549     }
5550 
5551     @Test
testApplyEnqueuedAdjustmentFromAssistant_singleUser()5552     public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
5553         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5554         mService.addEnqueuedNotification(r);
5555         NotificationManagerService.WorkerHandler handler = mock(
5556                 NotificationManagerService.WorkerHandler.class);
5557         mService.setHandler(handler);
5558         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5559 
5560         Bundle signals = new Bundle();
5561         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5562                 USER_SENTIMENT_NEGATIVE);
5563         Adjustment adjustment = new Adjustment(
5564                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5565         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5566 
5567         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
5568     }
5569 
5570     @Test
testApplyEnqueuedAdjustmentFromAssistant_importance()5571     public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
5572         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5573         mService.addEnqueuedNotification(r);
5574         NotificationManagerService.WorkerHandler handler = mock(
5575                 NotificationManagerService.WorkerHandler.class);
5576         mService.setHandler(handler);
5577         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5578 
5579         Bundle signals = new Bundle();
5580         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5581         Adjustment adjustment = new Adjustment(
5582                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5583         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5584 
5585         assertEquals(IMPORTANCE_LOW, r.getImportance());
5586     }
5587 
5588     @Test
testApplyEnqueuedAdjustmentFromAssistant_crossUser()5589     public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
5590         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5591         mService.addEnqueuedNotification(r);
5592         NotificationManagerService.WorkerHandler handler = mock(
5593                 NotificationManagerService.WorkerHandler.class);
5594         mService.setHandler(handler);
5595         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
5596 
5597         Bundle signals = new Bundle();
5598         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5599                 USER_SENTIMENT_NEGATIVE);
5600         Adjustment adjustment = new Adjustment(
5601                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5602         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5603 
5604         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5605 
5606         waitForIdle();
5607 
5608         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
5609     }
5610 
5611     @Test
testUserSentimentChangeTriggersUpdate()5612     public void testUserSentimentChangeTriggersUpdate() throws Exception {
5613         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5614         mService.addNotification(r);
5615         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5616 
5617         Bundle signals = new Bundle();
5618         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5619                 USER_SENTIMENT_NEGATIVE);
5620         Adjustment adjustment = new Adjustment(
5621                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5622         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5623 
5624         waitForIdle();
5625 
5626         verify(mRankingHandler, timeout(300).times(1)).requestSort();
5627     }
5628 
5629     @Test
testTooLateAdjustmentTriggersUpdate()5630     public void testTooLateAdjustmentTriggersUpdate() throws Exception {
5631         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5632         mService.addNotification(r);
5633         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5634 
5635         Bundle signals = new Bundle();
5636         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5637                 USER_SENTIMENT_NEGATIVE);
5638         Adjustment adjustment = new Adjustment(
5639                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5640         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5641 
5642         waitForIdle();
5643 
5644         verify(mRankingHandler, times(1)).requestSort();
5645     }
5646 
5647     @Test
testApplyAdjustmentsLogged()5648     public void testApplyAdjustmentsLogged() throws Exception {
5649         NotificationManagerService.WorkerHandler handler = mock(
5650                 NotificationManagerService.WorkerHandler.class);
5651         mService.setHandler(handler);
5652         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5653 
5654         // Set up notifications that will be adjusted
5655         final NotificationRecord r1 = generateNotificationRecord(
5656                 mTestNotificationChannel, 1, null, true);
5657         r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5658         mService.addNotification(r1);
5659         final NotificationRecord r2 = generateNotificationRecord(
5660                 mTestNotificationChannel, 2, null, true);
5661         r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5662         mService.addNotification(r2);
5663 
5664         // Third notification that's NOT adjusted, just to make sure that doesn't get spuriously
5665         // logged.
5666         final NotificationRecord r3 = generateNotificationRecord(
5667                 mTestNotificationChannel, 3, null, true);
5668         r3.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5669         mService.addNotification(r3);
5670 
5671         List<Adjustment> adjustments = new ArrayList<>();
5672 
5673         // Test an adjustment that's associated with a ranking change and one that's not
5674         Bundle signals1 = new Bundle();
5675         signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_HIGH);
5676         Adjustment adjustment1 = new Adjustment(
5677                 r1.getSbn().getPackageName(), r1.getKey(), signals1, "",
5678                 r1.getUser().getIdentifier());
5679         adjustments.add(adjustment1);
5680 
5681         // This one wouldn't trigger a ranking change, but should still trigger a log.
5682         Bundle signals2 = new Bundle();
5683         signals2.putFloat(Adjustment.KEY_RANKING_SCORE, -0.5f);
5684         Adjustment adjustment2 = new Adjustment(
5685                 r2.getSbn().getPackageName(), r2.getKey(), signals2, "",
5686                 r2.getUser().getIdentifier());
5687         adjustments.add(adjustment2);
5688 
5689         mBinderService.applyAdjustmentsFromAssistant(null, adjustments);
5690         verify(mRankingHandler, times(1)).requestSort();
5691 
5692         // Actually apply the adjustments & recalculate importance when run
5693         doAnswer(invocationOnMock -> {
5694             ((NotificationRecord) invocationOnMock.getArguments()[0])
5695                     .applyAdjustments();
5696             ((NotificationRecord) invocationOnMock.getArguments()[0])
5697                     .calculateImportance();
5698             return null;
5699         }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
5700 
5701         // Now make sure that when the sort happens, we actually log the changes.
5702         mService.handleRankingSort();
5703 
5704         // Even though the ranking score change is not meant to trigger a ranking update,
5705         // during this process the package visibility & canShowBadge values are changing
5706         // in all notifications, so all 3 seem to trigger a ranking change. Here we check instead
5707         // that scheduleSendRankingUpdate is sent and that the relevant fields have been changed
5708         // accordingly to confirm the adjustments happened to the 2 relevant notifications.
5709         verify(handler, times(3)).scheduleSendRankingUpdate();
5710         assertEquals(IMPORTANCE_HIGH, r1.getImportance());
5711         assertTrue(r2.rankingScoreMatches(-0.5f));
5712         assertEquals(2, mNotificationRecordLogger.numCalls());
5713         assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(0));
5714         assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(1));
5715         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
5716         assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId());
5717     }
5718 
5719     @Test
testAdjustmentToImportanceNone_cancelsNotification()5720     public void testAdjustmentToImportanceNone_cancelsNotification() throws Exception {
5721         NotificationManagerService.WorkerHandler handler = mock(
5722                 NotificationManagerService.WorkerHandler.class);
5723         mService.setHandler(handler);
5724         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5725         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
5726 
5727         // Set up notifications: r1 is adjusted, r2 is not
5728         final NotificationRecord r1 = generateNotificationRecord(
5729                 mTestNotificationChannel, 1, null, true);
5730         r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5731         mService.addNotification(r1);
5732         final NotificationRecord r2 = generateNotificationRecord(
5733                 mTestNotificationChannel, 2, null, true);
5734         r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5735         mService.addNotification(r2);
5736 
5737         // Test an adjustment that sets importance to none (meaning it's cancelling)
5738         Bundle signals1 = new Bundle();
5739         signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE);
5740         Adjustment adjustment1 = new Adjustment(
5741                 r1.getSbn().getPackageName(), r1.getKey(), signals1, "",
5742                 r1.getUser().getIdentifier());
5743 
5744         mBinderService.applyAdjustmentFromAssistant(null, adjustment1);
5745 
5746         // Actually apply the adjustments & recalculate importance when run
5747         doAnswer(invocationOnMock -> {
5748             ((NotificationRecord) invocationOnMock.getArguments()[0])
5749                     .applyAdjustments();
5750             ((NotificationRecord) invocationOnMock.getArguments()[0])
5751                     .calculateImportance();
5752             return null;
5753         }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
5754 
5755         // run the CancelNotificationRunnable when it happens
5756         ArgumentCaptor<NotificationManagerService.CancelNotificationRunnable> captor =
5757                 ArgumentCaptor.forClass(
5758                         NotificationManagerService.CancelNotificationRunnable.class);
5759 
5760         verify(handler, times(1)).scheduleCancelNotification(
5761                 captor.capture());
5762 
5763         // Run the runnable given to the cancel notification, and see if it logs properly
5764         NotificationManagerService.CancelNotificationRunnable runnable = captor.getValue();
5765         runnable.run();
5766         assertEquals(1, mNotificationRecordLogger.numCalls());
5767         assertEquals(
5768                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_ASSISTANT,
5769                 mNotificationRecordLogger.event(0));
5770     }
5771 
5772     @Test
testEnqueuedAdjustmentAppliesAdjustments()5773     public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
5774         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5775         mService.addEnqueuedNotification(r);
5776         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5777 
5778         Bundle signals = new Bundle();
5779         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5780                 USER_SENTIMENT_NEGATIVE);
5781         Adjustment adjustment = new Adjustment(
5782                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5783         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5784 
5785         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
5786     }
5787 
5788     @Test
testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications()5789     public void testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications() throws Exception {
5790         final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel);
5791         final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel);
5792         mService.addEnqueuedNotification(r1);
5793         mService.addEnqueuedNotification(r2);
5794         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5795 
5796         Bundle signals = new Bundle();
5797         signals.putInt(Adjustment.KEY_IMPORTANCE,
5798                 IMPORTANCE_HIGH);
5799         Adjustment adjustment = new Adjustment(
5800                 r1.getSbn().getPackageName(), r1.getKey(), signals,
5801                 "", r1.getUser().getIdentifier());
5802 
5803         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5804 
5805         assertEquals(IMPORTANCE_HIGH, r1.getImportance());
5806         assertEquals(IMPORTANCE_HIGH, r2.getImportance());
5807     }
5808 
5809     @Test
testRestore()5810     public void testRestore() throws Exception {
5811         int systemChecks = mService.countSystemChecks;
5812         mBinderService.applyRestore(null, USER_SYSTEM);
5813         assertEquals(1, mService.countSystemChecks - systemChecks);
5814     }
5815 
5816     @Test
testBackupEmptySound()5817     public void testBackupEmptySound() throws Exception {
5818         NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
5819         channel.setSound(Uri.EMPTY, null);
5820 
5821         TypedXmlSerializer serializer = Xml.newFastSerializer();
5822         ByteArrayOutputStream baos = new ByteArrayOutputStream();
5823         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
5824         channel.writeXmlForBackup(serializer, getContext());
5825 
5826         TypedXmlPullParser parser = Xml.newFastPullParser();
5827         parser.setInput(new BufferedInputStream(
5828                 new ByteArrayInputStream(baos.toByteArray())), null);
5829         NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
5830         restored.populateFromXmlForRestore(parser, true, getContext());
5831 
5832         assertNull(restored.getSound());
5833     }
5834 
5835     @Test
testBackup()5836     public void testBackup() throws Exception {
5837         mService.setPreferencesHelper(mPreferencesHelper);
5838         int systemChecks = mService.countSystemChecks;
5839         when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
5840                 .thenReturn(new ArraySet<>());
5841         mBinderService.getBackupPayload(1);
5842         assertEquals(1, mService.countSystemChecks - systemChecks);
5843     }
5844 
5845     @Test
testEmptyVibration_noException()5846     public void testEmptyVibration_noException() throws Exception {
5847         NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
5848         channel.setVibrationPattern(new long[0]);
5849 
5850         TypedXmlSerializer serializer = Xml.newFastSerializer();
5851         ByteArrayOutputStream baos = new ByteArrayOutputStream();
5852         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
5853         channel.writeXml(serializer);
5854     }
5855 
5856     @Test
updateUriPermissions_update()5857     public void updateUriPermissions_update() throws Exception {
5858         NotificationChannel c = new NotificationChannel(
5859                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
5860         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
5861         Message message1 = new Message("", 0, "");
5862         message1.setData("",
5863                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
5864         Message message2 = new Message("", 1, "");
5865         message2.setData("",
5866                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
5867 
5868         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
5869                 .setContentTitle("foo")
5870                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5871                 .setStyle(new Notification.MessagingStyle("")
5872                         .addMessage(message1)
5873                         .addMessage(message2));
5874         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
5875                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
5876                 null, 0), c);
5877 
5878         // First post means we grant access to both
5879         reset(mUgm);
5880         reset(mUgmInternal);
5881         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
5882         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
5883                 USER_SYSTEM);
5884         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
5885                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
5886         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
5887                 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
5888 
5889         Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
5890                 .setContentTitle("foo")
5891                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5892                 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
5893         NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
5894                 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
5895                 c);
5896 
5897         // Update means we drop access to first
5898         reset(mUgmInternal);
5899         mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
5900                 USER_SYSTEM);
5901         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
5902                 eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1));
5903 
5904         // Update back means we grant access to first again
5905         reset(mUgm);
5906         mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
5907                 USER_SYSTEM);
5908         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
5909                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
5910 
5911         // And update to empty means we drop everything
5912         reset(mUgmInternal);
5913         mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
5914                 USER_SYSTEM);
5915         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
5916                 anyInt(), anyInt());
5917     }
5918 
5919     @Test
updateUriPermissions_posterDoesNotOwnUri()5920     public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
5921         NotificationChannel c = new NotificationChannel(
5922                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
5923         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
5924         Message message1 = new Message("", 0, "");
5925         message1.setData("",
5926                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
5927 
5928         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
5929                 .setContentTitle("foo")
5930                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5931                 .setStyle(new Notification.MessagingStyle("")
5932                         .addMessage(message1));
5933         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
5934                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
5935                 null, 0), c);
5936 
5937         doThrow(new SecurityException("no access")).when(mUgm)
5938                 .grantUriPermissionFromOwner(
5939                         any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
5940 
5941         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
5942         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),  USER_SYSTEM);
5943 
5944         // yay, no crash
5945     }
5946 
5947     @Test
testVisitUris()5948     public void testVisitUris() throws Exception {
5949         final Uri audioContents = Uri.parse("content://com.example/audio");
5950         final Uri backgroundImage = Uri.parse("content://com.example/background");
5951         final Icon smallIcon = Icon.createWithContentUri("content://media/small/icon");
5952         final Icon largeIcon = Icon.createWithContentUri("content://media/large/icon");
5953         final Icon personIcon1 = Icon.createWithContentUri("content://media/person1");
5954         final Icon personIcon2 = Icon.createWithContentUri("content://media/person2");
5955         final Icon personIcon3 = Icon.createWithContentUri("content://media/person3");
5956         final Person person1 = new Person.Builder()
5957                 .setName("Messaging Person")
5958                 .setIcon(personIcon1)
5959                 .build();
5960         final Person person2 = new Person.Builder()
5961                 .setName("People List Person 1")
5962                 .setIcon(personIcon2)
5963                 .build();
5964         final Person person3 = new Person.Builder()
5965                 .setName("People List Person 2")
5966                 .setIcon(personIcon3)
5967                 .build();
5968         final Uri historyUri1 = Uri.parse("content://com.example/history1");
5969         final Uri historyUri2 = Uri.parse("content://com.example/history2");
5970         final RemoteInputHistoryItem historyItem1 = new RemoteInputHistoryItem(null, historyUri1,
5971                 "a");
5972         final RemoteInputHistoryItem historyItem2 = new RemoteInputHistoryItem(null, historyUri2,
5973                 "b");
5974 
5975         Bundle extras = new Bundle();
5976         extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
5977         extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
5978         extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1);
5979         extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST,
5980                 new ArrayList<>(Arrays.asList(person2, person3)));
5981         extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
5982                 new RemoteInputHistoryItem[]{historyItem1, historyItem2});
5983 
5984         Notification n = new Notification.Builder(mContext, "a")
5985                 .setContentTitle("notification with uris")
5986                 .setSmallIcon(smallIcon)
5987                 .setLargeIcon(largeIcon)
5988                 .addExtras(extras)
5989                 .build();
5990 
5991         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
5992         n.visitUris(visitor);
5993         verify(visitor, times(1)).accept(eq(audioContents));
5994         verify(visitor, times(1)).accept(eq(backgroundImage));
5995         verify(visitor, times(1)).accept(eq(smallIcon.getUri()));
5996         verify(visitor, times(1)).accept(eq(largeIcon.getUri()));
5997         verify(visitor, times(1)).accept(eq(personIcon1.getUri()));
5998         verify(visitor, times(1)).accept(eq(personIcon2.getUri()));
5999         verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
6000         verify(visitor, times(1)).accept(eq(historyUri1));
6001         verify(visitor, times(1)).accept(eq(historyUri2));
6002     }
6003 
6004     @Test
testVisitUris_publicVersion()6005     public void testVisitUris_publicVersion() throws Exception {
6006         final Icon smallIconPublic = Icon.createWithContentUri("content://media/small/icon");
6007         final Icon largeIconPrivate = Icon.createWithContentUri("content://media/large/icon");
6008 
6009         Notification publicVersion = new Notification.Builder(mContext, "a")
6010                 .setContentTitle("notification with uris")
6011                 .setSmallIcon(smallIconPublic)
6012                 .build();
6013         Notification n = new Notification.Builder(mContext, "a")
6014                 .setLargeIcon(largeIconPrivate)
6015                 .setPublicVersion(publicVersion)
6016                 .build();
6017 
6018         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6019         n.visitUris(visitor);
6020         verify(visitor, times(1)).accept(eq(smallIconPublic.getUri()));
6021         verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri()));
6022     }
6023 
6024     @Test
testVisitUris_audioContentsString()6025     public void testVisitUris_audioContentsString() throws Exception {
6026         final Uri audioContents = Uri.parse("content://com.example/audio");
6027 
6028         Bundle extras = new Bundle();
6029         extras.putString(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents.toString());
6030 
6031         Notification n = new Notification.Builder(mContext, "a")
6032                 .setContentTitle("notification with uris")
6033                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6034                 .addExtras(extras)
6035                 .build();
6036 
6037         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6038         n.visitUris(visitor);
6039         verify(visitor, times(1)).accept(eq(audioContents));
6040     }
6041 
6042     @Test
testVisitUris_messagingStyle()6043     public void testVisitUris_messagingStyle() {
6044         final Icon personIcon1 = Icon.createWithContentUri("content://media/person1");
6045         final Icon personIcon2 = Icon.createWithContentUri("content://media/person2");
6046         final Icon personIcon3 = Icon.createWithContentUri("content://media/person3");
6047         final Person person1 = new Person.Builder()
6048                 .setName("Messaging Person 1")
6049                 .setIcon(personIcon1)
6050                 .build();
6051         final Person person2 = new Person.Builder()
6052                 .setName("Messaging Person 2")
6053                 .setIcon(personIcon2)
6054                 .build();
6055         final Person person3 = new Person.Builder()
6056                 .setName("Messaging Person 3")
6057                 .setIcon(personIcon3)
6058                 .build();
6059         Icon shortcutIcon = Icon.createWithContentUri("content://media/shortcut");
6060 
6061         Notification.Builder builder = new Notification.Builder(mContext, "a")
6062                 .setCategory(Notification.CATEGORY_MESSAGE)
6063                 .setContentTitle("new message!")
6064                 .setContentText("Conversation Notification")
6065                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
6066         Notification.MessagingStyle.Message message1 = new Notification.MessagingStyle.Message(
6067                 "Marco?", System.currentTimeMillis(), person2);
6068         Notification.MessagingStyle.Message message2 = new Notification.MessagingStyle.Message(
6069                 "Polo!", System.currentTimeMillis(), person3);
6070         Notification.MessagingStyle style = new Notification.MessagingStyle(person1)
6071                 .addMessage(message1)
6072                 .addMessage(message2)
6073                 .setShortcutIcon(shortcutIcon);
6074         builder.setStyle(style);
6075         Notification n = builder.build();
6076 
6077         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6078         n.visitUris(visitor);
6079 
6080         verify(visitor, times(1)).accept(eq(shortcutIcon.getUri()));
6081         verify(visitor, times(1)).accept(eq(personIcon1.getUri()));
6082         verify(visitor, times(1)).accept(eq(personIcon2.getUri()));
6083         verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
6084     }
6085 
6086     @Test
testVisitUris_callStyle()6087     public void testVisitUris_callStyle() {
6088         Icon personIcon = Icon.createWithContentUri("content://media/person");
6089         Icon verificationIcon = Icon.createWithContentUri("content://media/verification");
6090         Person callingPerson = new Person.Builder().setName("Someone")
6091                 .setIcon(personIcon)
6092                 .build();
6093         PendingIntent hangUpIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
6094                 PendingIntent.FLAG_IMMUTABLE);
6095         Notification n = new Notification.Builder(mContext, "a")
6096                 .setStyle(Notification.CallStyle.forOngoingCall(callingPerson, hangUpIntent)
6097                         .setVerificationIcon(verificationIcon))
6098                 .setContentTitle("Calling...")
6099                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6100                 .build();
6101 
6102         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6103         n.visitUris(visitor);
6104 
6105         verify(visitor, times(1)).accept(eq(personIcon.getUri()));
6106         verify(visitor, times(1)).accept(eq(verificationIcon.getUri()));
6107     }
6108 
6109     @Test
testVisitUris_styleExtrasWithoutStyle()6110     public void testVisitUris_styleExtrasWithoutStyle() {
6111         Notification notification = new Notification.Builder(mContext, "a")
6112                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6113                 .build();
6114 
6115         Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(
6116                 personWithIcon("content://user"))
6117                 .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!",
6118                                 System.currentTimeMillis(),
6119                                 personWithIcon("content://historicalMessenger")))
6120                 .addMessage(new Notification.MessagingStyle.Message("Are you there",
6121                                 System.currentTimeMillis(),
6122                                 personWithIcon("content://messenger")))
6123                         .setShortcutIcon(
6124                                 Icon.createWithContentUri("content://conversationShortcut"));
6125         messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style).
6126 
6127         Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall(
6128                         personWithIcon("content://caller"),
6129                         PendingIntent.getActivity(mContext, 0, new Intent(),
6130                                 PendingIntent.FLAG_IMMUTABLE))
6131                 .setVerificationIcon(Icon.createWithContentUri("content://callVerification"));
6132         callStyle.addExtras(notification.extras); // Same.
6133 
6134         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6135         notification.visitUris(visitor);
6136 
6137         verify(visitor).accept(eq(Uri.parse("content://user")));
6138         verify(visitor).accept(eq(Uri.parse("content://historicalMessenger")));
6139         verify(visitor).accept(eq(Uri.parse("content://messenger")));
6140         verify(visitor).accept(eq(Uri.parse("content://conversationShortcut")));
6141         verify(visitor).accept(eq(Uri.parse("content://caller")));
6142         verify(visitor).accept(eq(Uri.parse("content://callVerification")));
6143     }
6144 
personWithIcon(String iconUri)6145     private static Person personWithIcon(String iconUri) {
6146         return new Person.Builder()
6147                 .setName("Mr " + iconUri)
6148                 .setIcon(Icon.createWithContentUri(iconUri))
6149                 .build();
6150     }
6151 
6152     @Test
testVisitUris_wearableExtender()6153     public void testVisitUris_wearableExtender() {
6154         Icon actionIcon = Icon.createWithContentUri("content://media/action");
6155         Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction");
6156         PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(),
6157                 PendingIntent.FLAG_IMMUTABLE);
6158         Notification n = new Notification.Builder(mContext, "a")
6159                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6160                 .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build())
6161                 .extend(new Notification.WearableExtender().addAction(
6162                         new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build()))
6163                 .build();
6164 
6165         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6166         n.visitUris(visitor);
6167 
6168         verify(visitor).accept(eq(actionIcon.getUri()));
6169         verify(visitor).accept(eq(wearActionIcon.getUri()));
6170     }
6171 
6172     @Test
testSetNotificationPolicy_preP_setOldFields()6173     public void testSetNotificationPolicy_preP_setOldFields() {
6174         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6175         mService.mZenModeHelper = mZenModeHelper;
6176         NotificationManager.Policy userPolicy =
6177                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6178         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6179 
6180         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6181                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
6182 
6183         int expected = SUPPRESSED_EFFECT_BADGE
6184                 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
6185                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
6186                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6187         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
6188 
6189         assertEquals(expected, actual);
6190     }
6191 
6192     @Test
testSetNotificationPolicy_preP_setNewFields()6193     public void testSetNotificationPolicy_preP_setNewFields() {
6194         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6195         mService.mZenModeHelper = mZenModeHelper;
6196         NotificationManager.Policy userPolicy =
6197                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6198         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6199 
6200         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6201                 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
6202 
6203         int expected = SUPPRESSED_EFFECT_BADGE;
6204         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
6205 
6206         assertEquals(expected, actual);
6207     }
6208 
6209     @Test
testSetNotificationPolicy_preP_setOldNewFields()6210     public void testSetNotificationPolicy_preP_setOldNewFields() {
6211         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6212         mService.mZenModeHelper = mZenModeHelper;
6213         NotificationManager.Policy userPolicy =
6214                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6215         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6216 
6217         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6218                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
6219 
6220         int expected =
6221                 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
6222         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
6223 
6224         assertEquals(expected, actual);
6225     }
6226 
6227     @Test
testSetNotificationPolicy_P_setOldFields()6228     public void testSetNotificationPolicy_P_setOldFields() {
6229         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6230         mService.mZenModeHelper = mZenModeHelper;
6231         NotificationManager.Policy userPolicy =
6232                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6233         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6234 
6235         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6236                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
6237 
6238         int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
6239                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
6240                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6241         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6242 
6243         assertEquals(expected, actual);
6244     }
6245 
6246     @Test
testSetNotificationPolicy_P_setNewFields()6247     public void testSetNotificationPolicy_P_setNewFields() {
6248         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6249         mService.mZenModeHelper = mZenModeHelper;
6250         NotificationManager.Policy userPolicy =
6251                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6252         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6253 
6254         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6255                 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
6256                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
6257 
6258         int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
6259                 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
6260                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6261         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6262 
6263         assertEquals(expected, actual);
6264     }
6265 
6266     @Test
testSetNotificationPolicy_P_setOldNewFields()6267     public void testSetNotificationPolicy_P_setOldNewFields() {
6268         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6269         mService.mZenModeHelper = mZenModeHelper;
6270         NotificationManager.Policy userPolicy =
6271                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6272         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6273 
6274         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6275                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
6276 
6277         int expected =  SUPPRESSED_EFFECT_STATUS_BAR;
6278         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6279 
6280         assertEquals(expected, actual);
6281 
6282         appPolicy = new NotificationManager.Policy(0, 0, 0,
6283                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
6284                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
6285 
6286         expected =  SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
6287                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6288         actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6289 
6290         assertEquals(expected, actual);
6291     }
6292 
6293     @Test
testVisualDifference_foreground()6294     public void testVisualDifference_foreground() {
6295         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6296                 .setContentTitle("foo");
6297         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6298                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6299         NotificationRecord r1 =
6300                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6301 
6302         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6303                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
6304                 .setContentTitle("bar");
6305         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6306                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6307         NotificationRecord r2 =
6308                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6309 
6310         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6311     }
6312 
6313     @Test
testVisualDifference_diffTitle()6314     public void testVisualDifference_diffTitle() {
6315         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6316                 .setContentTitle("foo");
6317         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6318                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6319         NotificationRecord r1 =
6320                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6321 
6322         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6323                 .setContentTitle("bar");
6324         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6325                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6326         NotificationRecord r2 =
6327                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6328 
6329         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6330     }
6331 
6332     @Test
testVisualDifference_inboxStyle()6333     public void testVisualDifference_inboxStyle() {
6334         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6335                 .setStyle(new Notification.InboxStyle()
6336                     .addLine("line1").addLine("line2"));
6337         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6338                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6339         NotificationRecord r1 =
6340                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6341 
6342         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6343                 .setStyle(new Notification.InboxStyle()
6344                         .addLine("line1").addLine("line2_changed"));
6345         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6346                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6347         NotificationRecord r2 =
6348                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6349 
6350         assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
6351 
6352         Notification.Builder nb3 = new Notification.Builder(mContext, "")
6353                 .setStyle(new Notification.InboxStyle()
6354                         .addLine("line1"));
6355         StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6356                 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6357         NotificationRecord r3 =
6358                 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
6359 
6360         assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
6361 
6362         Notification.Builder nb4 = new Notification.Builder(mContext, "")
6363                 .setStyle(new Notification.InboxStyle()
6364                         .addLine("line1").addLine("line2").addLine("line3"));
6365         StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6366                 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6367         NotificationRecord r4 =
6368                 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
6369 
6370         assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
6371 
6372         Notification.Builder nb5 = new Notification.Builder(mContext, "")
6373             .setContentText("not an inbox");
6374         StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6375                 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6376         NotificationRecord r5 =
6377                 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
6378 
6379         assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
6380     }
6381 
6382     @Test
testVisualDifference_diffText()6383     public void testVisualDifference_diffText() {
6384         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6385                 .setContentText("foo");
6386         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6387                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6388         NotificationRecord r1 =
6389                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6390 
6391         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6392                 .setContentText("bar");
6393         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6394                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6395         NotificationRecord r2 =
6396                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6397 
6398         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6399     }
6400 
6401     @Test
testVisualDifference_sameText()6402     public void testVisualDifference_sameText() {
6403         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6404                 .setContentText("foo");
6405         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6406                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6407         NotificationRecord r1 =
6408                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6409 
6410         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6411                 .setContentText("foo");
6412         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6413                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6414         NotificationRecord r2 =
6415                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6416 
6417         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6418     }
6419 
6420     @Test
testVisualDifference_sameTextButStyled()6421     public void testVisualDifference_sameTextButStyled() {
6422         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6423                 .setContentText(Html.fromHtml("<b>foo</b>"));
6424         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6425                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6426         NotificationRecord r1 =
6427                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6428 
6429         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6430                 .setContentText(Html.fromHtml("<b>foo</b>"));
6431         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6432                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6433         NotificationRecord r2 =
6434                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6435 
6436         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6437     }
6438 
6439     @Test
testVisualDifference_diffTextButStyled()6440     public void testVisualDifference_diffTextButStyled() {
6441         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6442                 .setContentText(Html.fromHtml("<b>foo</b>"));
6443         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6444                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6445         NotificationRecord r1 =
6446                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6447 
6448         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6449                 .setContentText(Html.fromHtml("<b>bar</b>"));
6450         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6451                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6452         NotificationRecord r2 =
6453                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6454 
6455         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6456     }
6457 
6458     @Test
testVisualDifference_diffProgress()6459     public void testVisualDifference_diffProgress() {
6460         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6461                 .setProgress(100, 90, false);
6462         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6463                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6464         NotificationRecord r1 =
6465                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6466 
6467         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6468                 .setProgress(100, 100, false);
6469         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6470                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6471         NotificationRecord r2 =
6472                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6473 
6474         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6475     }
6476 
6477     @Test
testVisualDifference_diffProgressNotDone()6478     public void testVisualDifference_diffProgressNotDone() {
6479         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6480                 .setProgress(100, 90, false);
6481         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6482                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6483         NotificationRecord r1 =
6484                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6485 
6486         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6487                 .setProgress(100, 91, false);
6488         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6489                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6490         NotificationRecord r2 =
6491                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6492 
6493         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6494     }
6495 
6496     @Test
testVisualDifference_sameProgressStillDone()6497     public void testVisualDifference_sameProgressStillDone() {
6498         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6499                 .setProgress(100, 100, false);
6500         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6501                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6502         NotificationRecord r1 =
6503                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6504 
6505         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6506                 .setProgress(100, 100, false);
6507         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6508                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6509         NotificationRecord r2 =
6510                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6511 
6512         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6513     }
6514 
6515     @Test
testVisualDifference_summary()6516     public void testVisualDifference_summary() {
6517         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6518                 .setGroup("bananas")
6519                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
6520                 .setContentText("foo");
6521         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6522                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6523         NotificationRecord r1 =
6524                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6525 
6526         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6527                 .setGroup("bananas")
6528                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
6529                 .setContentText("bar");
6530         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6531                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6532         NotificationRecord r2 =
6533                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6534 
6535         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6536     }
6537 
6538     @Test
testVisualDifference_summaryNewNotification()6539     public void testVisualDifference_summaryNewNotification() {
6540         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6541                 .setGroup("bananas")
6542                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
6543                 .setContentText("bar");
6544         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6545                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6546         NotificationRecord r2 =
6547                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6548 
6549         assertFalse(mService.isVisuallyInterruptive(null, r2));
6550     }
6551 
6552     @Test
testVisualDifference_sameImages()6553     public void testVisualDifference_sameImages() {
6554         Icon large = Icon.createWithResource(mContext, 1);
6555         Notification n1 = new Notification.Builder(mContext, "channel")
6556                 .setSmallIcon(1).setLargeIcon(large).build();
6557         Notification n2 = new Notification.Builder(mContext, "channel")
6558                 .setSmallIcon(1).setLargeIcon(large).build();
6559 
6560         NotificationRecord r1 = notificationToRecord(n1);
6561         NotificationRecord r2 = notificationToRecord(n2);
6562 
6563         assertThat(mService.isVisuallyInterruptive(r1, r2)).isFalse();
6564     }
6565 
6566     @Test
testVisualDifference_differentSmallImage()6567     public void testVisualDifference_differentSmallImage() {
6568         Icon large = Icon.createWithResource(mContext, 1);
6569         Notification n1 = new Notification.Builder(mContext, "channel")
6570                 .setSmallIcon(1).setLargeIcon(large).build();
6571         Notification n2 = new Notification.Builder(mContext, "channel")
6572                 .setSmallIcon(2).setLargeIcon(large).build();
6573 
6574         NotificationRecord r1 = notificationToRecord(n1);
6575         NotificationRecord r2 = notificationToRecord(n2);
6576 
6577         assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue();
6578     }
6579 
6580     @Test
testVisualDifference_differentLargeImage()6581     public void testVisualDifference_differentLargeImage() {
6582         Icon large1 = Icon.createWithResource(mContext, 1);
6583         Icon large2 = Icon.createWithResource(mContext, 2);
6584         Notification n1 = new Notification.Builder(mContext, "channel")
6585                 .setSmallIcon(1).setLargeIcon(large1).build();
6586         Notification n2 = new Notification.Builder(mContext, "channel")
6587                 .setSmallIcon(1).setLargeIcon(large2).build();
6588 
6589         NotificationRecord r1 = notificationToRecord(n1);
6590         NotificationRecord r2 = notificationToRecord(n2);
6591 
6592         assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue();
6593     }
6594 
notificationToRecord(Notification n)6595     private NotificationRecord notificationToRecord(Notification n) {
6596         return new NotificationRecord(
6597                 mContext,
6598                 new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, n,
6599                         UserHandle.getUserHandleForUid(mUid), null, 0),
6600                 mock(NotificationChannel.class));
6601     }
6602 
6603     @Test
testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()6604     public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
6605         // post 2 notification from this package
6606         final NotificationRecord notif1 = generateNotificationRecord(
6607                 mTestNotificationChannel, 1, null, true);
6608         final NotificationRecord notif2 = generateNotificationRecord(
6609                 mTestNotificationChannel, 2, null, false);
6610         mService.addNotification(notif1);
6611         mService.addNotification(notif2);
6612 
6613         // on broadcast, hide the 2 notifications
6614         simulatePackageSuspendBroadcast(true, PKG, notif1.getUid());
6615         ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
6616         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
6617         assertEquals(2, captorHide.getValue().size());
6618 
6619         // on broadcast, unhide the 2 notifications
6620         simulatePackageSuspendBroadcast(false, PKG, notif1.getUid());
6621         ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
6622         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
6623         assertEquals(2, captorUnhide.getValue().size());
6624     }
6625 
6626     @Test
testNoNotificationsHiddenOnSuspendedPackageBroadcast()6627     public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
6628         // post 2 notification from this package
6629         final NotificationRecord notif1 = generateNotificationRecord(
6630                 mTestNotificationChannel, 1, null, true);
6631         final NotificationRecord notif2 = generateNotificationRecord(
6632                 mTestNotificationChannel, 2, null, false);
6633         mService.addNotification(notif1);
6634         mService.addNotification(notif2);
6635 
6636         // on broadcast, nothing is hidden since no notifications are of package "test_package"
6637         simulatePackageSuspendBroadcast(true, "test_package", notif1.getUid());
6638         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
6639         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
6640         assertEquals(0, captor.getValue().size());
6641     }
6642 
6643     @Test
testNotificationFromDifferentUserHidden()6644     public void testNotificationFromDifferentUserHidden() {
6645         // post 2 notification from this package
6646         final NotificationRecord notif1 = generateNotificationRecord(
6647                 mTestNotificationChannel, 1, null, true);
6648         final NotificationRecord notif2 = generateNotificationRecord(
6649                 mTestNotificationChannel, 2, null, false);
6650         mService.addNotification(notif1);
6651         mService.addNotification(notif2);
6652 
6653         // on broadcast, nothing is hidden since no notifications are of user 10 with package PKG
6654         simulatePackageSuspendBroadcast(true, PKG, 10);
6655         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
6656         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
6657         assertEquals(0, captor.getValue().size());
6658     }
6659 
6660     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast()6661     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
6662         // Post 2 notifications from 2 packages
6663         NotificationRecord pkgA = new NotificationRecord(mContext,
6664                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
6665         mService.addNotification(pkgA);
6666         NotificationRecord pkgB = new NotificationRecord(mContext,
6667                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
6668         mService.addNotification(pkgB);
6669 
6670         // on broadcast, hide one of the packages
6671         simulatePackageDistractionBroadcast(
6672                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"},
6673                 new int[] {1000});
6674         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
6675         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
6676         assertEquals(1, captorHide.getValue().size());
6677         assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
6678 
6679         // on broadcast, unhide the package
6680         simulatePackageDistractionBroadcast(
6681                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"},
6682                 new int[] {1000});
6683         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
6684         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
6685         assertEquals(1, captorUnhide.getValue().size());
6686         assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
6687     }
6688 
6689     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()6690     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
6691         // Post 2 notifications from 2 packages
6692         NotificationRecord pkgA = new NotificationRecord(mContext,
6693                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
6694         mService.addNotification(pkgA);
6695         NotificationRecord pkgB = new NotificationRecord(mContext,
6696                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
6697         mService.addNotification(pkgB);
6698 
6699         // on broadcast, hide one of the packages
6700         simulatePackageDistractionBroadcast(
6701                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"},
6702                 new int[] {1000, 1001});
6703         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
6704 
6705         // should be called only once.
6706         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
6707         assertEquals(2, captorHide.getValue().size());
6708         assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
6709         assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
6710 
6711         // on broadcast, unhide the package
6712         simulatePackageDistractionBroadcast(
6713                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"},
6714                 new int[] {1000, 1001});
6715         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
6716 
6717         // should be called only once.
6718         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
6719         assertEquals(2, captorUnhide.getValue().size());
6720         assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
6721         assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
6722     }
6723 
6724     @Test
testNoNotificationsHiddenOnDistractingPackageBroadcast()6725     public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
6726         // post notification from this package
6727         final NotificationRecord notif1 = generateNotificationRecord(
6728                 mTestNotificationChannel, 1, null, true);
6729         mService.addNotification(notif1);
6730 
6731         // on broadcast, nothing is hidden since no notifications are of package "test_package"
6732         simulatePackageDistractionBroadcast(
6733                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"},
6734                 new int[]{notif1.getUid()});
6735         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
6736         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
6737         assertEquals(0, captor.getValue().size());
6738     }
6739 
6740     @Test
testCanUseManagedServicesNullPkg()6741     public void testCanUseManagedServicesNullPkg() {
6742         assertEquals(true, mService.canUseManagedServices(null, 0, null));
6743     }
6744 
6745 
6746     @Test
testCanUseManagedServicesNoValidPkg()6747     public void testCanUseManagedServicesNoValidPkg() {
6748         assertEquals(true, mService.canUseManagedServices("d", 0, null));
6749     }
6750 
6751     @Test
testCanUseManagedServices_hasPermission()6752     public void testCanUseManagedServices_hasPermission() throws Exception {
6753         when(mPackageManager.checkPermission("perm", "pkg", 0))
6754                 .thenReturn(PackageManager.PERMISSION_GRANTED);
6755 
6756         assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
6757     }
6758 
6759     @Test
testCanUseManagedServices_noPermission()6760     public void testCanUseManagedServices_noPermission() throws Exception {
6761         when(mPackageManager.checkPermission("perm", "pkg", 0))
6762                 .thenReturn(PackageManager.PERMISSION_DENIED);
6763 
6764         assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
6765     }
6766 
6767     @Test
testCanUseManagedServices_permDoesNotMatter()6768     public void testCanUseManagedServices_permDoesNotMatter() {
6769         assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
6770     }
6771 
6772     @Test
testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()6773     public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
6774         final NotificationRecord r = generateNotificationRecord(
6775                 mTestNotificationChannel, 1, null, true);
6776         r.setTextChanged(true);
6777         mService.addNotification(r);
6778 
6779         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
6780                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
6781                 new NotificationVisibility[]{});
6782 
6783         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
6784     }
6785 
6786     @Test
testOnNotificationVisibilityChanged_triggersVisibilityLog()6787     public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
6788         final NotificationRecord r = generateNotificationRecord(
6789                 mTestNotificationChannel, 1, null, true);
6790         r.setTextChanged(true);
6791         r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
6792         mService.addNotification(r);
6793 
6794         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
6795                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
6796                 new NotificationVisibility[]{});
6797 
6798         assertEquals(1, mNotificationRecordLogger.numCalls());
6799         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
6800                 mNotificationRecordLogger.event(0));
6801         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
6802 
6803         mService.mNotificationDelegate.onNotificationVisibilityChanged(
6804                 new NotificationVisibility[]{},
6805                 new NotificationVisibility[]
6806                         {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
6807         );
6808 
6809         assertEquals(2, mNotificationRecordLogger.numCalls());
6810         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
6811                 mNotificationRecordLogger.event(1));
6812         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
6813     }
6814 
6815     @Test
testSetNotificationsShownFromListener_triggersInterruptionUsageStat()6816     public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
6817             throws RemoteException {
6818         final NotificationRecord r = generateNotificationRecord(
6819                 mTestNotificationChannel, 1, null, true);
6820         r.setTextChanged(true);
6821         mService.addNotification(r);
6822 
6823         mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
6824 
6825         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
6826     }
6827 
6828     @Test
testSetNotificationsShownFromListener_protectsCrossUserInformation()6829     public void testSetNotificationsShownFromListener_protectsCrossUserInformation()
6830             throws RemoteException {
6831         Notification.Builder nb = new Notification.Builder(
6832                 mContext, mTestNotificationChannel.getId())
6833                 .setContentTitle("foo")
6834                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
6835         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6836                 "tag" + System.currentTimeMillis(),  UserHandle.PER_USER_RANGE, 0,
6837                 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE),
6838                 null, 0);
6839         final NotificationRecord r =
6840                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6841         r.setTextChanged(true);
6842         mService.addNotification(r);
6843 
6844         // no security exception!
6845         mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
6846 
6847         verify(mAppUsageStats, never()).reportInterruptiveNotification(
6848                 anyString(), anyString(), anyInt());
6849     }
6850 
6851     @Test
testCancelNotificationsFromListener_protectsCrossUserInformation()6852     public void testCancelNotificationsFromListener_protectsCrossUserInformation()
6853             throws RemoteException {
6854         Notification.Builder nb = new Notification.Builder(
6855                 mContext, mTestNotificationChannel.getId())
6856                 .setContentTitle("foo")
6857                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
6858         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6859                 "tag" + System.currentTimeMillis(),  UserHandle.PER_USER_RANGE, 0,
6860                 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE),
6861                 null, 0);
6862         final NotificationRecord r =
6863                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6864         r.setTextChanged(true);
6865         mService.addNotification(r);
6866 
6867         // no security exception!
6868         mBinderService.cancelNotificationsFromListener(null, new String[] {r.getKey()});
6869 
6870         waitForIdle();
6871         assertEquals(1, mService.getNotificationRecordCount());
6872     }
6873 
6874     @Test
testMaybeRecordInterruptionLocked_doesNotRecordTwice()6875     public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
6876             throws RemoteException {
6877         final NotificationRecord r = generateNotificationRecord(
6878                 mTestNotificationChannel, 1, null, true);
6879         r.setInterruptive(true);
6880         mService.addNotification(r);
6881 
6882         mService.maybeRecordInterruptionLocked(r);
6883         mService.maybeRecordInterruptionLocked(r);
6884 
6885         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
6886                 anyString(), anyString(), anyInt());
6887         verify(mHistoryManager, times(1)).addNotification(any());
6888     }
6889 
6890     @Test
testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory()6891     public void testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory()
6892             throws RemoteException {
6893         final NotificationRecord r = generateNotificationRecord(
6894                 mTestNotificationChannel, 1, null, true);
6895         r.setInterruptive(true);
6896         r.getSbn().getNotification().setSmallIcon(null);
6897         mService.addNotification(r);
6898 
6899         mService.maybeRecordInterruptionLocked(r);
6900 
6901         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
6902                 anyString(), anyString(), anyInt());
6903         verify(mHistoryManager, never()).addNotification(any());
6904     }
6905 
6906     @Test
testBubble()6907     public void testBubble() throws Exception {
6908         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
6909         assertFalse(mBinderService.areBubblesAllowed(PKG));
6910         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
6911                 BUBBLE_PREFERENCE_NONE);
6912     }
6913 
6914     @Test
testUserApprovedBubblesForPackageSelected()6915     public void testUserApprovedBubblesForPackageSelected() throws Exception {
6916         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
6917         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
6918                 BUBBLE_PREFERENCE_SELECTED);
6919     }
6920 
6921     @Test
testUserApprovedBubblesForPackageAll()6922     public void testUserApprovedBubblesForPackageAll() throws Exception {
6923         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
6924         assertTrue(mBinderService.areBubblesAllowed(PKG));
6925         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
6926                 BUBBLE_PREFERENCE_ALL);
6927     }
6928 
6929     @Test
testUserRejectsBubblesForPackage()6930     public void testUserRejectsBubblesForPackage() throws Exception {
6931         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
6932         assertFalse(mBinderService.areBubblesAllowed(PKG));
6933     }
6934 
6935     @Test
testAreBubblesEnabled()6936     public void testAreBubblesEnabled() throws Exception {
6937         Settings.Secure.putInt(mContext.getContentResolver(),
6938                 Settings.Secure.NOTIFICATION_BUBBLES, 1);
6939         mService.mPreferencesHelper.updateBubblesEnabled();
6940         assertTrue(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid)));
6941     }
6942 
6943     @Test
testAreBubblesEnabled_false()6944     public void testAreBubblesEnabled_false() throws Exception {
6945         Settings.Secure.putInt(mContext.getContentResolver(),
6946                 Settings.Secure.NOTIFICATION_BUBBLES, 0);
6947         mService.mPreferencesHelper.updateBubblesEnabled();
6948         assertFalse(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid)));
6949     }
6950 
6951     @Test
testAreBubblesEnabled_exception()6952     public void testAreBubblesEnabled_exception() throws Exception {
6953         try {
6954             assertTrue(mBinderService.areBubblesEnabled(
6955                     UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE)));
6956             fail("Cannot call cross user without permission");
6957         } catch (SecurityException e) {
6958             // pass
6959         }
6960         // cross user, with permission, no problem
6961         enableInteractAcrossUsers();
6962         assertTrue(mBinderService.areBubblesEnabled(
6963                 UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE)));
6964     }
6965 
6966     @Test
testIsCallerInstantApp_primaryUser()6967     public void testIsCallerInstantApp_primaryUser() throws Exception {
6968         ApplicationInfo info = new ApplicationInfo();
6969         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
6970         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
6971         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
6972 
6973         assertTrue(mService.isCallerInstantApp(45770, 0));
6974 
6975         info.privateFlags = 0;
6976         assertFalse(mService.isCallerInstantApp(575370, 0));
6977     }
6978 
6979     @Test
testIsCallerInstantApp_secondaryUser()6980     public void testIsCallerInstantApp_secondaryUser() throws Exception {
6981         ApplicationInfo info = new ApplicationInfo();
6982         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
6983         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info);
6984         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null);
6985         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
6986 
6987         assertTrue(mService.isCallerInstantApp(68638450, 10));
6988     }
6989 
6990     @Test
testIsCallerInstantApp_userAllNotification()6991     public void testIsCallerInstantApp_userAllNotification() throws Exception {
6992         ApplicationInfo info = new ApplicationInfo();
6993         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
6994         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(USER_SYSTEM)))
6995                 .thenReturn(info);
6996         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
6997 
6998         assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
6999 
7000         info.privateFlags = 0;
7001         assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
7002     }
7003 
7004     @Test
testResolveNotificationUid_sameApp_nonSystemUser()7005     public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
7006         ApplicationInfo info = new ApplicationInfo();
7007         info.uid = Binder.getCallingUid();
7008         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info);
7009         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null);
7010 
7011         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
7012 
7013         assertEquals(info.uid, actualUid);
7014     }
7015 
7016     @Test
testResolveNotificationUid_sameApp()7017     public void testResolveNotificationUid_sameApp() throws Exception {
7018         ApplicationInfo info = new ApplicationInfo();
7019         info.uid = Binder.getCallingUid();
7020         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
7021 
7022         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
7023 
7024         assertEquals(info.uid, actualUid);
7025     }
7026 
7027     @Test
testResolveNotificationUid_sameAppDiffPackage()7028     public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
7029         ApplicationInfo info = new ApplicationInfo();
7030         info.uid = Binder.getCallingUid();
7031         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
7032 
7033         int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
7034 
7035         assertEquals(info.uid, actualUid);
7036     }
7037 
7038     @Test
testResolveNotificationUid_sameAppWrongUid()7039     public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
7040         ApplicationInfo info = new ApplicationInfo();
7041         info.uid = 1356347;
7042         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(info);
7043 
7044         try {
7045             mService.resolveNotificationUid("caller", "caller", 9, 0);
7046             fail("Incorrect uid didn't throw security exception");
7047         } catch (SecurityException e) {
7048             // yay
7049         }
7050     }
7051 
7052     @Test
testResolveNotificationUid_delegateAllowed()7053     public void testResolveNotificationUid_delegateAllowed() throws Exception {
7054         int expectedUid = 123;
7055 
7056         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
7057         mService.setPreferencesHelper(mPreferencesHelper);
7058         when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
7059                 .thenReturn(true);
7060 
7061         assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
7062     }
7063 
7064     @Test
testResolveNotificationUid_androidAllowed()7065     public void testResolveNotificationUid_androidAllowed() throws Exception {
7066         int expectedUid = 123;
7067 
7068         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
7069         // no delegate
7070 
7071         assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
7072     }
7073 
7074     @Test
testPostFromAndroidForNonExistentPackage()7075     public void testPostFromAndroidForNonExistentPackage() throws Exception {
7076         final String notReal = "NOT REAL";
7077         when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
7078                 PackageManager.NameNotFoundException.class);
7079         ApplicationInfo ai = new ApplicationInfo();
7080         ai.uid = -1;
7081         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai);
7082 
7083         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
7084         try {
7085             mInternalService.enqueueNotification(notReal, "android", 0, 0,
7086                     "testPostFromAndroidForNonExistentPackage",
7087                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
7088             fail("can't post notifications for nonexistent packages, even if you exist");
7089         } catch (SecurityException e) {
7090             // yay
7091         }
7092     }
7093 
7094     @Test
testCancelFromAndroidForNonExistentPackage()7095     public void testCancelFromAndroidForNonExistentPackage() throws Exception {
7096         final String notReal = "NOT REAL";
7097         when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
7098                 PackageManager.NameNotFoundException.class);
7099         ApplicationInfo ai = new ApplicationInfo();
7100         ai.uid = -1;
7101         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai);
7102 
7103         // unlike the post case, ignore instead of throwing
7104         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
7105 
7106         mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
7107                 sbn.getId(), sbn.getUserId());
7108     }
7109 
7110     @Test
testResolveNotificationUid_delegateNotAllowed()7111     public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
7112         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
7113         // no delegate
7114 
7115         try {
7116             mService.resolveNotificationUid("caller", "target", 9, 0);
7117             fail("Incorrect uid didn't throw security exception");
7118         } catch (SecurityException e) {
7119             // yay
7120         }
7121     }
7122 
7123     @Test
testRemoveForegroundServiceFlagFromNotification_enqueued()7124     public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
7125         when(mAmi.applyForegroundServiceNotification(
7126                 any(), anyString(), anyInt(), anyString(), anyInt()))
7127                 .thenReturn(SHOW_IMMEDIATELY);
7128         Notification n = new Notification.Builder(mContext, "").build();
7129         n.flags |= FLAG_FOREGROUND_SERVICE;
7130 
7131         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
7132                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7133         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7134 
7135         mService.addEnqueuedNotification(r);
7136 
7137         mInternalService.removeForegroundServiceFlagFromNotification(
7138                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7139 
7140         waitForIdle();
7141 
7142         verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
7143     }
7144 
7145     @Test
testRemoveForegroundServiceFlagFromNotification_posted()7146     public void testRemoveForegroundServiceFlagFromNotification_posted() {
7147         when(mAmi.applyForegroundServiceNotification(
7148                 any(), anyString(), anyInt(), anyString(), anyInt()))
7149                 .thenReturn(SHOW_IMMEDIATELY);
7150         Notification n = new Notification.Builder(mContext, "").build();
7151         n.flags |= FLAG_FOREGROUND_SERVICE;
7152 
7153         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
7154                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7155         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7156 
7157         mService.addNotification(r);
7158 
7159         mInternalService.removeForegroundServiceFlagFromNotification(
7160                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7161 
7162         waitForIdle();
7163 
7164         ArgumentCaptor<NotificationRecord> captor =
7165                 ArgumentCaptor.forClass(NotificationRecord.class);
7166         verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
7167 
7168         assertEquals(0, captor.getValue().getNotification().flags);
7169     }
7170 
7171     @Test
testCannotRemoveForegroundFlagWhenOverLimit_enqueued()7172     public void testCannotRemoveForegroundFlagWhenOverLimit_enqueued() {
7173         when(mAmi.applyForegroundServiceNotification(
7174                 any(), anyString(), anyInt(), anyString(), anyInt()))
7175                 .thenReturn(SHOW_IMMEDIATELY);
7176         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7177             Notification n = new Notification.Builder(mContext, "").build();
7178             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
7179                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
7180             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7181             mService.addEnqueuedNotification(r);
7182         }
7183         Notification n = new Notification.Builder(mContext, "").build();
7184         n.flags |= FLAG_FOREGROUND_SERVICE;
7185 
7186         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
7187                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
7188                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7189         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7190 
7191         mService.addEnqueuedNotification(r);
7192 
7193         mInternalService.removeForegroundServiceFlagFromNotification(
7194                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7195 
7196         waitForIdle();
7197 
7198         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
7199                 mService.getNotificationRecordCount());
7200     }
7201 
7202     @Test
testCannotRemoveForegroundFlagWhenOverLimit_posted()7203     public void testCannotRemoveForegroundFlagWhenOverLimit_posted() {
7204         when(mAmi.applyForegroundServiceNotification(
7205                 any(), anyString(), anyInt(), anyString(), anyInt()))
7206                 .thenReturn(SHOW_IMMEDIATELY);
7207         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7208             Notification n = new Notification.Builder(mContext, "").build();
7209             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
7210                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
7211             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7212             mService.addNotification(r);
7213         }
7214         Notification n = new Notification.Builder(mContext, "").build();
7215         n.flags |= FLAG_FOREGROUND_SERVICE;
7216 
7217         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
7218                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
7219                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7220         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7221 
7222         mService.addNotification(r);
7223 
7224         mInternalService.removeForegroundServiceFlagFromNotification(
7225                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7226 
7227         waitForIdle();
7228 
7229         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
7230                 mService.getNotificationRecordCount());
7231     }
7232 
7233     @Test
testAllowForegroundCustomToasts()7234     public void testAllowForegroundCustomToasts() throws Exception {
7235         final String testPackage = "testPackageName";
7236         assertEquals(0, mService.mToastQueue.size());
7237         mService.isSystemUid = false;
7238         mService.isSystemAppId = false;
7239         setToastRateIsWithinQuota(true);
7240         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7241 
7242         // package is not suspended
7243         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7244                 .thenReturn(false);
7245 
7246         // notifications from this package are blocked by the user
7247         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
7248 
7249         setAppInForegroundForToasts(mUid, true);
7250 
7251         // enqueue toast -> toast should still enqueue
7252         enqueueToast(testPackage, new TestableToastCallback());
7253         assertEquals(1, mService.mToastQueue.size());
7254     }
7255 
7256     @Test
testDisallowBackgroundCustomToasts()7257     public void testDisallowBackgroundCustomToasts() throws Exception {
7258         final String testPackage = "testPackageName";
7259         assertEquals(0, mService.mToastQueue.size());
7260         mService.isSystemUid = false;
7261         mService.isSystemAppId = false;
7262         setToastRateIsWithinQuota(true);
7263         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7264 
7265         // package is not suspended
7266         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7267                 .thenReturn(false);
7268 
7269         setAppInForegroundForToasts(mUid, false);
7270 
7271         // enqueue toast -> no toasts enqueued
7272         enqueueToast(testPackage, new TestableToastCallback());
7273         assertEquals(0, mService.mToastQueue.size());
7274     }
7275 
7276     @Test
testDontCallShowToastAgainOnTheSameCustomToast()7277     public void testDontCallShowToastAgainOnTheSameCustomToast() throws Exception {
7278         final String testPackage = "testPackageName";
7279         assertEquals(0, mService.mToastQueue.size());
7280         mService.isSystemUid = false;
7281         mService.isSystemAppId = false;
7282         setToastRateIsWithinQuota(true);
7283         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7284 
7285         // package is not suspended
7286         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7287                 .thenReturn(false);
7288 
7289         setAppInForegroundForToasts(mUid, true);
7290 
7291         Binder token = new Binder();
7292         ITransientNotification callback = mock(ITransientNotification.class);
7293         INotificationManager nmService = (INotificationManager) mService.mService;
7294 
7295         // first time trying to show the toast, showToast gets called
7296         enqueueToast(nmService, testPackage, token, callback);
7297         verify(callback, times(1)).show(any());
7298 
7299         // second time trying to show the same toast, showToast isn't called again (total number of
7300         // invocations stays at one)
7301         enqueueToast(nmService, testPackage, token, callback);
7302         verify(callback, times(1)).show(any());
7303     }
7304 
7305     @Test
testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground()7306     public void testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground()
7307             throws Exception {
7308         final String testPackage = "testPackageName";
7309         assertEquals(0, mService.mToastQueue.size());
7310         mService.isSystemUid = false;
7311         mService.isSystemAppId = false;
7312         setToastRateIsWithinQuota(false); // rate limit reached
7313         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7314 
7315         // package is not suspended
7316         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7317                 .thenReturn(false);
7318 
7319         setAppInForegroundForToasts(mUid, true);
7320 
7321         Binder token = new Binder();
7322         ITransientNotification callback = mock(ITransientNotification.class);
7323         INotificationManager nmService = (INotificationManager) mService.mService;
7324 
7325         enqueueToast(nmService, testPackage, token, callback);
7326         verify(callback, times(1)).show(any());
7327     }
7328 
7329     @Test
testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()7330     public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()
7331             throws Exception {
7332         final String testPackage = "testPackageName";
7333         assertEquals(0, mService.mToastQueue.size());
7334         mService.isSystemUid = false;
7335         mService.isSystemAppId = false;
7336         setToastRateIsWithinQuota(true);
7337         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7338 
7339         // package is not suspended
7340         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7341                 .thenReturn(false);
7342 
7343         setAppInForegroundForToasts(mUid, true);
7344 
7345         Binder token1 = new Binder();
7346         Binder token2 = new Binder();
7347         ITransientNotification callback1 = mock(ITransientNotification.class);
7348         ITransientNotification callback2 = mock(ITransientNotification.class);
7349         INotificationManager nmService = (INotificationManager) mService.mService;
7350 
7351         enqueueToast(nmService, testPackage, token1, callback1);
7352         enqueueToast(nmService, testPackage, token2, callback2);
7353 
7354         assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued.
7355         verify(callback1, times(1)).show(any()); // First toast shown.
7356 
7357         setAppInForegroundForToasts(mUid, false);
7358 
7359         mService.cancelToastLocked(0); // Remove the first toast, and show next.
7360 
7361         assertEquals(0, mService.mToastQueue.size()); // Both toasts processed.
7362         verify(callback2, never()).show(any()); // Second toast was never shown.
7363     }
7364 
7365     @Test
testAllowForegroundTextToasts()7366     public void testAllowForegroundTextToasts() throws Exception {
7367         final String testPackage = "testPackageName";
7368         assertEquals(0, mService.mToastQueue.size());
7369         mService.isSystemUid = false;
7370         mService.isSystemAppId = false;
7371         setToastRateIsWithinQuota(true);
7372         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7373 
7374         // package is not suspended
7375         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7376                 .thenReturn(false);
7377 
7378         setAppInForegroundForToasts(mUid, true);
7379 
7380         // enqueue toast -> toast should still enqueue
7381         enqueueTextToast(testPackage, "Text");
7382         assertEquals(1, mService.mToastQueue.size());
7383     }
7384 
7385     @Test
testAllowBackgroundTextToasts()7386     public void testAllowBackgroundTextToasts() throws Exception {
7387         final String testPackage = "testPackageName";
7388         assertEquals(0, mService.mToastQueue.size());
7389         mService.isSystemUid = false;
7390         mService.isSystemAppId = false;
7391         setToastRateIsWithinQuota(true);
7392         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7393 
7394         // package is not suspended
7395         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7396                 .thenReturn(false);
7397 
7398         setAppInForegroundForToasts(mUid, false);
7399 
7400         // enqueue toast -> toast should still enqueue
7401         enqueueTextToast(testPackage, "Text");
7402         assertEquals(1, mService.mToastQueue.size());
7403     }
7404 
7405     @Test
testDontCallShowToastAgainOnTheSameTextToast()7406     public void testDontCallShowToastAgainOnTheSameTextToast() throws Exception {
7407         final String testPackage = "testPackageName";
7408         assertEquals(0, mService.mToastQueue.size());
7409         mService.isSystemUid = false;
7410         mService.isSystemAppId = false;
7411         setToastRateIsWithinQuota(true);
7412         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7413 
7414         // package is not suspended
7415         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7416                 .thenReturn(false);
7417 
7418         setAppInForegroundForToasts(mUid, true);
7419 
7420         Binder token = new Binder();
7421         INotificationManager nmService = (INotificationManager) mService.mService;
7422 
7423         // first time trying to show the toast, showToast gets called
7424         enqueueTextToast(testPackage, "Text");
7425         verify(mStatusBar, times(1))
7426                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7427 
7428         // second time trying to show the same toast, showToast isn't called again (total number of
7429         // invocations stays at one)
7430         enqueueTextToast(testPackage, "Text");
7431         verify(mStatusBar, times(1))
7432                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7433     }
7434 
7435     @Test
testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground()7436     public void testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground()
7437             throws Exception {
7438         final String testPackage = "testPackageName";
7439         assertEquals(0, mService.mToastQueue.size());
7440         mService.isSystemUid = false;
7441         mService.isSystemAppId = false;
7442         setToastRateIsWithinQuota(false); // rate limit reached
7443         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7444         setAppInForegroundForToasts(mUid, false);
7445 
7446         // package is not suspended
7447         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7448                 .thenReturn(false);
7449 
7450         Binder token = new Binder();
7451         INotificationManager nmService = (INotificationManager) mService.mService;
7452 
7453         enqueueTextToast(testPackage, "Text");
7454         verify(mStatusBar, times(0))
7455                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7456     }
7457 
7458     @Test
testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground()7459     public void testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground()
7460             throws Exception {
7461         final String testPackage = "testPackageName";
7462         assertEquals(0, mService.mToastQueue.size());
7463         mService.isSystemUid = false;
7464         mService.isSystemAppId = false;
7465         setToastRateIsWithinQuota(false); // rate limit reached
7466         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7467         setAppInForegroundForToasts(mUid, true);
7468 
7469         // package is not suspended
7470         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7471                 .thenReturn(false);
7472 
7473         Binder token = new Binder();
7474         INotificationManager nmService = (INotificationManager) mService.mService;
7475 
7476         enqueueTextToast(testPackage, "Text");
7477         verify(mStatusBar, times(1))
7478                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7479     }
7480 
7481     @Test
testTextToastRateLimiterAllowsLimitAvoidanceWithPermission()7482     public void testTextToastRateLimiterAllowsLimitAvoidanceWithPermission() throws Exception {
7483         final String testPackage = "testPackageName";
7484         assertEquals(0, mService.mToastQueue.size());
7485         mService.isSystemUid = false;
7486         mService.isSystemAppId = false;
7487         setToastRateIsWithinQuota(false); // rate limit reached
7488         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, true);
7489         setAppInForegroundForToasts(mUid, false);
7490 
7491         // package is not suspended
7492         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7493                 .thenReturn(false);
7494 
7495         Binder token = new Binder();
7496         INotificationManager nmService = (INotificationManager) mService.mService;
7497 
7498         enqueueTextToast(testPackage, "Text");
7499         verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
7500                 anyInt());
7501     }
7502 
7503     @Test
testRateLimitedToasts_windowsRemoved()7504     public void testRateLimitedToasts_windowsRemoved() throws Exception {
7505         final String testPackage = "testPackageName";
7506         assertEquals(0, mService.mToastQueue.size());
7507         mService.isSystemUid = false;
7508         mService.isSystemAppId = false;
7509         setToastRateIsWithinQuota(false); // rate limit reached
7510         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7511         setAppInForegroundForToasts(mUid, false);
7512 
7513         // package is not suspended
7514         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7515                 .thenReturn(false);
7516 
7517         Binder token = new Binder();
7518         INotificationManager nmService = (INotificationManager) mService.mService;
7519 
7520         enqueueTextToast(testPackage, "Text");
7521 
7522         // window token was added when enqueued
7523         ArgumentCaptor<Binder> binderCaptor =
7524                 ArgumentCaptor.forClass(Binder.class);
7525         verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(),
7526                 eq(TYPE_TOAST), anyInt(), eq(null));
7527 
7528         // but never shown
7529         verify(mStatusBar, times(0))
7530                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7531 
7532         // and removed when rate limited
7533         verify(mWindowManagerInternal)
7534                 .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt());
7535     }
7536 
7537     @Test
backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast()7538     public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws
7539             Exception {
7540         final String testPackage = "testPackageName";
7541         assertEquals(0, mService.mToastQueue.size());
7542         mService.isSystemUid = true;
7543         setToastRateIsWithinQuota(true);
7544         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7545 
7546         // package is not suspended
7547         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7548                 .thenReturn(false);
7549 
7550         // notifications from this package are blocked by the user
7551         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
7552 
7553         setAppInForegroundForToasts(mUid, false);
7554 
7555         // enqueue toast -> toast should still enqueue
7556         enqueueToast(testPackage, new TestableToastCallback());
7557         assertEquals(1, mService.mToastQueue.size());
7558         verify(mAm).setProcessImportant(any(), anyInt(), eq(true), any());
7559     }
7560 
7561     @Test
foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7562     public void foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws
7563             Exception {
7564         final String testPackage = "testPackageName";
7565         assertEquals(0, mService.mToastQueue.size());
7566         mService.isSystemUid = false;
7567         mService.isSystemAppId = false;
7568         setToastRateIsWithinQuota(true);
7569         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7570 
7571         // package is not suspended
7572         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7573                 .thenReturn(false);
7574 
7575         setAppInForegroundForToasts(mUid, true);
7576 
7577         // enqueue toast -> toast should still enqueue
7578         enqueueTextToast(testPackage, "Text");
7579         assertEquals(1, mService.mToastQueue.size());
7580         verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
7581     }
7582 
7583     @Test
backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7584     public void backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws
7585             Exception {
7586         final String testPackage = "testPackageName";
7587         assertEquals(0, mService.mToastQueue.size());
7588         mService.isSystemUid = false;
7589         mService.isSystemAppId = false;
7590         setToastRateIsWithinQuota(true);
7591         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7592 
7593         // package is not suspended
7594         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7595                 .thenReturn(false);
7596 
7597         setAppInForegroundForToasts(mUid, false);
7598 
7599         // enqueue toast -> toast should still enqueue
7600         enqueueTextToast(testPackage, "Text");
7601         assertEquals(1, mService.mToastQueue.size());
7602         verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
7603     }
7604 
7605     @Test
testTextToastsCallStatusBar()7606     public void testTextToastsCallStatusBar() throws Exception {
7607         allowTestPackageToToast();
7608 
7609         // enqueue toast -> no toasts enqueued
7610         enqueueTextToast(TEST_PACKAGE, "Text");
7611 
7612         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
7613     }
7614 
7615     @Test
testTextToastsCallStatusBar_nonUiContext_defaultDisplay()7616     public void testTextToastsCallStatusBar_nonUiContext_defaultDisplay()
7617             throws Exception {
7618         allowTestPackageToToast();
7619 
7620         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY);
7621 
7622         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
7623     }
7624 
7625     @Test
testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()7626     public void testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()
7627             throws Exception {
7628         allowTestPackageToToast();
7629         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7630 
7631         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID);
7632 
7633         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7634     }
7635 
7636     @Test
testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay()7637     public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay()
7638             throws Exception {
7639         mockIsVisibleBackgroundUsersSupported(true);
7640         mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID);
7641         allowTestPackageToToast();
7642 
7643         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, DEFAULT_DISPLAY);
7644 
7645         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
7646 
7647     }
7648 
7649     @Test
testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()7650     public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()
7651             throws Exception {
7652         mockIsVisibleBackgroundUsersSupported(true);
7653         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7654         mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used
7655         allowTestPackageToToast();
7656 
7657         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, SECONDARY_DISPLAY_ID);
7658 
7659         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7660     }
7661 
7662     @Test
testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay()7663     public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay()
7664             throws Exception {
7665         mockIsVisibleBackgroundUsersSupported(true);
7666         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7667         mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID);
7668         allowTestPackageToToast();
7669 
7670         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY);
7671 
7672         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7673     }
7674 
7675     @Test
testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()7676     public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()
7677             throws Exception {
7678         mockIsVisibleBackgroundUsersSupported(true);
7679         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7680         mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used
7681         allowTestPackageToToast();
7682 
7683         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID);
7684 
7685         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7686     }
7687 
7688     @Test
testTextToastsCallStatusBar_userNotVisibleOnDisplay()7689     public void testTextToastsCallStatusBar_userNotVisibleOnDisplay() throws Exception {
7690         final String testPackage = "testPackageName";
7691         assertEquals(0, mService.mToastQueue.size());
7692         mService.isSystemUid = false;
7693         mService.isSystemAppId = false;
7694         setToastRateIsWithinQuota(true);
7695         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7696         mockIsUserVisible(DEFAULT_DISPLAY, false);
7697 
7698         // package is not suspended
7699         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
7700                 .thenReturn(false);
7701 
7702         // enqueue toast -> no toasts enqueued
7703         enqueueTextToast(testPackage, "Text");
7704         verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
7705                 anyInt());
7706         assertEquals(0, mService.mToastQueue.size());
7707     }
7708 
7709     @Test
testDisallowToastsFromSuspendedPackages()7710     public void testDisallowToastsFromSuspendedPackages() throws Exception {
7711         final String testPackage = "testPackageName";
7712         assertEquals(0, mService.mToastQueue.size());
7713         mService.isSystemUid = false;
7714         mService.isSystemAppId = false;
7715         setToastRateIsWithinQuota(true);
7716         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7717 
7718         // package is suspended
7719         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7720                 .thenReturn(true);
7721 
7722         // notifications from this package are NOT blocked by the user
7723         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
7724 
7725         // enqueue toast -> no toasts enqueued
7726         enqueueToast(testPackage, new TestableToastCallback());
7727         verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
7728                 anyInt());
7729         assertEquals(0, mService.mToastQueue.size());
7730     }
7731 
7732     @Test
testDisallowToastsFromBlockedApps()7733     public void testDisallowToastsFromBlockedApps() throws Exception {
7734         final String testPackage = "testPackageName";
7735         assertEquals(0, mService.mToastQueue.size());
7736         mService.isSystemUid = false;
7737         mService.isSystemAppId = false;
7738         setToastRateIsWithinQuota(true);
7739         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7740 
7741         // package is not suspended
7742         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7743                 .thenReturn(false);
7744 
7745         // notifications from this package are blocked by the user
7746         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
7747 
7748         setAppInForegroundForToasts(mUid, false);
7749 
7750         // enqueue toast -> no toasts enqueued
7751         enqueueToast(testPackage, new TestableToastCallback());
7752         assertEquals(0, mService.mToastQueue.size());
7753     }
7754 
7755     @Test
testAlwaysAllowSystemToasts()7756     public void testAlwaysAllowSystemToasts() throws Exception {
7757         final String testPackage = "testPackageName";
7758         assertEquals(0, mService.mToastQueue.size());
7759         mService.isSystemUid = true;
7760         setToastRateIsWithinQuota(true);
7761         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7762 
7763         // package is suspended
7764         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7765                 .thenReturn(true);
7766 
7767         // notifications from this package ARE blocked by the user
7768         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
7769 
7770         setAppInForegroundForToasts(mUid, false);
7771 
7772         // enqueue toast -> system toast can still be enqueued
7773         enqueueToast(testPackage, new TestableToastCallback());
7774         assertEquals(1, mService.mToastQueue.size());
7775     }
7776 
7777     @Test
testLimitNumberOfQueuedToastsFromPackage()7778     public void testLimitNumberOfQueuedToastsFromPackage() throws Exception {
7779         final String testPackage = "testPackageName";
7780         assertEquals(0, mService.mToastQueue.size());
7781         mService.isSystemUid = false;
7782         mService.isSystemAppId = false;
7783         setToastRateIsWithinQuota(true);
7784         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7785 
7786         // package is not suspended
7787         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7788                 .thenReturn(false);
7789 
7790         INotificationManager nmService = (INotificationManager) mService.mService;
7791 
7792         // Trying to quickly enqueue more toast than allowed.
7793         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS + 1; i++) {
7794             enqueueTextToast(testPackage, "Text");
7795         }
7796         // Only allowed number enqueued, rest ignored.
7797         assertEquals(NotificationManagerService.MAX_PACKAGE_TOASTS, mService.mToastQueue.size());
7798     }
7799 
7800     @Test
testPrioritizeSystemToasts()7801     public void testPrioritizeSystemToasts() throws Exception {
7802         // Insert non-system toasts
7803         final String testPackage = "testPackageName";
7804         assertEquals(0, mService.mToastQueue.size());
7805         mService.isSystemUid = false;
7806         mService.isSystemAppId = false;
7807         setToastRateIsWithinQuota(true);
7808         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7809 
7810         // package is not suspended
7811         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7812                 .thenReturn(false);
7813 
7814         INotificationManager nmService = (INotificationManager) mService.mService;
7815 
7816         // Enqueue maximum number of toasts for test package
7817         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS; i++) {
7818             enqueueTextToast(testPackage, "Text");
7819         }
7820 
7821         // Enqueue system toast
7822         final String testPackageSystem = "testPackageNameSystem";
7823         mService.isSystemUid = true;
7824         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem, false);
7825         when(mPackageManager.isPackageSuspendedForUser(testPackageSystem, mUserId))
7826                 .thenReturn(false);
7827 
7828         enqueueToast(testPackageSystem, new TestableToastCallback());
7829 
7830         // System toast is inserted at the front of the queue, behind current showing toast
7831         assertEquals(testPackageSystem, mService.mToastQueue.get(1).pkg);
7832     }
7833 
7834     @Test
testPrioritizeSystemToasts_enqueueAfterExistingSystemToast()7835     public void testPrioritizeSystemToasts_enqueueAfterExistingSystemToast() throws Exception {
7836         // Insert system toasts
7837         final String testPackageSystem1 = "testPackageNameSystem1";
7838         assertEquals(0, mService.mToastQueue.size());
7839         mService.isSystemUid = true;
7840         setToastRateIsWithinQuota(true);
7841         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem1, false);
7842 
7843         // package is not suspended
7844         when(mPackageManager.isPackageSuspendedForUser(testPackageSystem1, mUserId))
7845                 .thenReturn(false);
7846 
7847         INotificationManager nmService = (INotificationManager) mService.mService;
7848 
7849         // Enqueue maximum number of toasts for test package
7850         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS; i++) {
7851             enqueueTextToast(testPackageSystem1, "Text");
7852         }
7853 
7854         // Enqueue another system toast
7855         final String testPackageSystem2 = "testPackageNameSystem2";
7856         mService.isSystemUid = true;
7857         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem2, false);
7858         when(mPackageManager.isPackageSuspendedForUser(testPackageSystem2, mUserId))
7859                 .thenReturn(false);
7860 
7861         enqueueToast(testPackageSystem2, new TestableToastCallback());
7862 
7863         // System toast is inserted at the back of the queue, after the other system toasts
7864         assertEquals(testPackageSystem2,
7865                 mService.mToastQueue.get(mService.mToastQueue.size() - 1).pkg);
7866     }
7867 
setAppInForegroundForToasts(int uid, boolean inForeground)7868     private void setAppInForegroundForToasts(int uid, boolean inForeground) {
7869         int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
7870         when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
7871         when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
7872     }
7873 
setToastRateIsWithinQuota(boolean isWithinQuota)7874     private void setToastRateIsWithinQuota(boolean isWithinQuota) {
7875         when(mToastRateLimiter.isWithinQuota(
7876                 anyInt(),
7877                 anyString(),
7878                 eq(NotificationManagerService.TOAST_QUOTA_TAG)))
7879                 .thenReturn(isWithinQuota);
7880     }
7881 
setIfPackageHasPermissionToAvoidToastRateLimiting( String pkg, boolean hasPermission)7882     private void setIfPackageHasPermissionToAvoidToastRateLimiting(
7883             String pkg, boolean hasPermission) throws Exception {
7884         when(mPackageManager.checkPermission(android.Manifest.permission.UNLIMITED_TOASTS,
7885                 pkg, mUserId))
7886                 .thenReturn(hasPermission ? PERMISSION_GRANTED : PERMISSION_DENIED);
7887     }
7888 
7889     @Test
testOnPanelRevealedAndHidden()7890     public void testOnPanelRevealedAndHidden() {
7891         int items = 5;
7892         mService.mNotificationDelegate.onPanelRevealed(false, items);
7893         verify(mAssistants, times(1)).onPanelRevealed(eq(items));
7894 
7895         mService.mNotificationDelegate.onPanelHidden();
7896         verify(mAssistants, times(1)).onPanelHidden();
7897 
7898         assertEquals(2, mNotificationRecordLogger.numCalls());
7899         assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
7900                 mNotificationRecordLogger.event(0));
7901         assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
7902                 mNotificationRecordLogger.event(1));
7903     }
7904 
7905     @Test
testOnNotificationSmartReplySent()7906     public void testOnNotificationSmartReplySent() {
7907         final int replyIndex = 2;
7908         final String reply = "Hello";
7909         final boolean modifiedBeforeSending = true;
7910         final boolean generatedByAssistant = true;
7911 
7912         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7913         r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
7914         mService.addNotification(r);
7915 
7916         mService.mNotificationDelegate.onNotificationSmartReplySent(
7917                 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
7918                 modifiedBeforeSending);
7919         verify(mAssistants).notifyAssistantSuggestedReplySent(
7920                 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(reply), eq(generatedByAssistant));
7921         assertEquals(1, mNotificationRecordLogger.numCalls());
7922         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
7923                 mNotificationRecordLogger.event(0));
7924     }
7925 
7926     @Test
testOnNotificationActionClick()7927     public void testOnNotificationActionClick() {
7928         final int actionIndex = 2;
7929         final Notification.Action action =
7930                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
7931                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
7932         final boolean generatedByAssistant = false;
7933 
7934         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7935         mService.addNotification(r);
7936 
7937         NotificationVisibility notificationVisibility =
7938                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
7939         mService.mNotificationDelegate.onNotificationActionClick(
7940                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
7941                 generatedByAssistant);
7942         verify(mAssistants).notifyAssistantActionClicked(
7943                 eq(r), eq(action), eq(generatedByAssistant));
7944 
7945         assertEquals(1, mNotificationRecordLogger.numCalls());
7946         assertEquals(
7947                 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2,
7948                 mNotificationRecordLogger.event(0));
7949     }
7950 
7951     @Test
testOnAssistantNotificationActionClick()7952     public void testOnAssistantNotificationActionClick() {
7953         final int actionIndex = 1;
7954         final Notification.Action action =
7955                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
7956                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
7957         final boolean generatedByAssistant = true;
7958 
7959         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7960         mService.addNotification(r);
7961 
7962         NotificationVisibility notificationVisibility =
7963                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
7964         mService.mNotificationDelegate.onNotificationActionClick(
7965                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
7966                 generatedByAssistant);
7967         verify(mAssistants).notifyAssistantActionClicked(
7968                 eq(r), eq(action), eq(generatedByAssistant));
7969 
7970         assertEquals(1, mNotificationRecordLogger.numCalls());
7971         assertEquals(
7972                 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1,
7973                 mNotificationRecordLogger.event(0));
7974     }
7975 
7976     @Test
testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()7977     public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
7978         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7979         mService.addNotification(r);
7980 
7981         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
7982                 NOTIFICATION_LOCATION_UNKNOWN);
7983         NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
7984                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
7985         };
7986         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
7987                 new NotificationVisibility[0]);
7988 
7989         assertEquals(1, mService.countLogSmartSuggestionsVisible);
7990     }
7991 
7992     @Test
testLogSmartSuggestionsVisible_noTriggerOnExpand()7993     public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
7994         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7995         mService.addNotification(r);
7996 
7997         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
7998                 NOTIFICATION_LOCATION_UNKNOWN);
7999 
8000         assertEquals(0, mService.countLogSmartSuggestionsVisible);
8001     }
8002 
8003     @Test
testLogSmartSuggestionsVisible_noTriggerOnVisible()8004     public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
8005         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
8006         mService.addNotification(r);
8007 
8008         NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
8009                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
8010         };
8011         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
8012                 new NotificationVisibility[0]);
8013 
8014         assertEquals(0, mService.countLogSmartSuggestionsVisible);
8015     }
8016 
8017     @Test
testReportSeen_delegated()8018     public void testReportSeen_delegated() {
8019         Notification.Builder nb =
8020                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
8021                         .setContentTitle("foo")
8022                         .setSmallIcon(android.R.drawable.sym_def_app_icon);
8023 
8024         StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
8025                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8026         NotificationRecord r =  new NotificationRecord(mContext, sbn, mTestNotificationChannel);
8027 
8028         mService.reportSeen(r);
8029         verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
8030 
8031     }
8032 
8033     @Test
testReportSeen_notDelegated()8034     public void testReportSeen_notDelegated() {
8035         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
8036 
8037         mService.reportSeen(r);
8038         verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
8039     }
8040 
8041     @Test
testNotificationStats_notificationError()8042     public void testNotificationStats_notificationError() {
8043         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
8044         mService.addNotification(r);
8045 
8046         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
8047                 r.getSbn().getTag(), mUid, 0,
8048                 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
8049                 UserHandle.getUserHandleForUid(mUid), null, 0);
8050         NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
8051         mService.addEnqueuedNotification(update);
8052         assertNull(update.getSbn().getNotification().getSmallIcon());
8053 
8054         NotificationManagerService.PostNotificationRunnable runnable =
8055                 mService.new PostNotificationRunnable(update.getKey(), r.getSbn().getPackageName(),
8056                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
8057         runnable.run();
8058         waitForIdle();
8059 
8060         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
8061         verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
8062         assertNotNull(captor.getValue());
8063     }
8064 
8065     @Test
testCanNotifyAsUser_crossUser()8066     public void testCanNotifyAsUser_crossUser() throws Exception {
8067         // same user no problem
8068         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
8069 
8070         // cross user, no permission, problem
8071         try {
8072             mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
8073             fail("Should not be callable cross user without cross user permission");
8074         } catch (SecurityException e) {
8075             // good
8076         }
8077 
8078         // cross user, with permission, no problem
8079         enableInteractAcrossUsers();
8080         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
8081     }
8082 
8083     @Test
testGetNotificationChannels_crossUser()8084     public void testGetNotificationChannels_crossUser() throws Exception {
8085         // same user no problem
8086         mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
8087 
8088         // cross user, no permission, problem
8089         try {
8090             mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
8091             fail("Should not be callable cross user without cross user permission");
8092         } catch (SecurityException e) {
8093             // good
8094         }
8095 
8096         // cross user, with permission, no problem
8097         enableInteractAcrossUsers();
8098         mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
8099     }
8100 
8101     @Test
setDefaultAssistantForUser_fromConfigXml()8102     public void setDefaultAssistantForUser_fromConfigXml() {
8103         clearDeviceConfig();
8104         ComponentName xmlConfig = new ComponentName("config", "xml");
8105         ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
8106         when(mResources
8107                 .getString(
8108                         com.android.internal.R.string.config_defaultAssistantAccessComponent))
8109                 .thenReturn(xmlConfig.flattenToString());
8110         when(mContext.getResources()).thenReturn(mResources);
8111         when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
8112                 .thenReturn(components);
8113         when(mAssistants.getDefaultComponents())
8114                 .thenReturn(components);
8115         mService.setNotificationAssistantAccessGrantedCallback(
8116                 mNotificationAssistantAccessGrantedCallback);
8117 
8118 
8119         mService.setDefaultAssistantForUser(0);
8120 
8121         verify(mNotificationAssistantAccessGrantedCallback)
8122                 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false));
8123     }
8124 
8125     @Test
setDefaultAssistantForUser_fromDeviceConfig()8126     public void setDefaultAssistantForUser_fromDeviceConfig() {
8127         ComponentName xmlConfig = new ComponentName("xml", "config");
8128         ComponentName deviceConfig = new ComponentName("device", "config");
8129         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
8130         when(mResources
8131                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
8132                 .thenReturn(xmlConfig.flattenToString());
8133         when(mContext.getResources()).thenReturn(mResources);
8134         when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
8135                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
8136         when(mAssistants.getDefaultComponents())
8137                 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
8138         mService.setNotificationAssistantAccessGrantedCallback(
8139                 mNotificationAssistantAccessGrantedCallback);
8140 
8141         mService.setDefaultAssistantForUser(0);
8142 
8143         verify(mNotificationAssistantAccessGrantedCallback)
8144                 .onGranted(eq(deviceConfig), eq(0), eq(true), eq(false));
8145     }
8146 
8147     @Test
setDefaultAssistantForUser_deviceConfigInvalid()8148     public void setDefaultAssistantForUser_deviceConfigInvalid() {
8149         ComponentName xmlConfig = new ComponentName("xml", "config");
8150         ComponentName deviceConfig = new ComponentName("device", "config");
8151         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
8152         when(mResources
8153                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
8154                 .thenReturn(xmlConfig.flattenToString());
8155         when(mContext.getResources()).thenReturn(mResources);
8156         // Only xmlConfig is valid, deviceConfig is not.
8157         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
8158                 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
8159         when(mAssistants.getDefaultComponents())
8160                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
8161         mService.setNotificationAssistantAccessGrantedCallback(
8162                 mNotificationAssistantAccessGrantedCallback);
8163 
8164         mService.setDefaultAssistantForUser(0);
8165 
8166         verify(mNotificationAssistantAccessGrantedCallback)
8167                 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false));
8168     }
8169 
8170     @Test
clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne()8171     public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
8172         ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
8173                 generateResetComponentValues();
8174         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
8175         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
8176         ComponentName deviceConfig1 = new ComponentName("device", "config1");
8177         ComponentName deviceConfig2 = new ComponentName("device", "config2");
8178         changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
8179         changes.put(false, new ArrayList());
8180         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
8181         mService.getBinderService().clearData("device", 0, false);
8182         verify(mAssistants, times(1))
8183                 .setPackageOrComponentEnabled(
8184                         eq("device/config2"),
8185                         eq(0), eq(true), eq(false));
8186         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
8187                 eq("device"), eq(0), eq(false), eq(true));
8188     }
8189 
8190     @Test
testNASSettingUpgrade_userSetNull()8191     public void testNASSettingUpgrade_userSetNull() throws RemoteException {
8192         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component1");
8193         TestableNotificationManagerService service = spy(mService);
8194         int userId = 11;
8195         setUsers(new int[]{userId});
8196         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
8197         setNASMigrationDone(false, userId);
8198         when(mAssistants.getDefaultFromConfig())
8199                 .thenReturn(newDefaultComponent);
8200         when(mAssistants.getAllowedComponents(anyInt()))
8201                 .thenReturn(new ArrayList<>());
8202         when(mAssistants.hasUserSet(userId)).thenReturn(true);
8203 
8204         service.migrateDefaultNAS();
8205         assertTrue(service.isNASMigrationDone(userId));
8206         verify(mAssistants, times(1)).clearDefaults();
8207     }
8208 
8209     @Test
testNASSettingUpgrade_userSet()8210     public void testNASSettingUpgrade_userSet() throws RemoteException {
8211         ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component1");
8212         TestableNotificationManagerService service = spy(mService);
8213         int userId = 11;
8214         setUsers(new int[]{userId});
8215         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
8216         setNASMigrationDone(false, userId);
8217         when(mAssistants.getDefaultFromConfig())
8218                 .thenReturn(defaultComponent);
8219         when(mAssistants.getAllowedComponents(anyInt()))
8220                 .thenReturn(new ArrayList(Arrays.asList(defaultComponent)));
8221         when(mAssistants.hasUserSet(userId)).thenReturn(true);
8222 
8223         service.migrateDefaultNAS();
8224         verify(mAssistants, times(1)).setUserSet(userId, false);
8225         //resetDefaultAssistantsIfNecessary should invoke from readPolicyXml() and migration
8226         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
8227     }
8228 
8229     @Test
testNASSettingUpgrade_multiUser()8230     public void testNASSettingUpgrade_multiUser() throws RemoteException {
8231         ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1");
8232         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2");
8233         TestableNotificationManagerService service = spy(mService);
8234         int userId1 = 11;
8235         int userId2 = 12;
8236         setUsers(new int[]{userId1, userId2});
8237         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1});
8238         when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2});
8239 
8240         setNASMigrationDone(false, userId1);
8241         setNASMigrationDone(false, userId2);
8242         when(mAssistants.getDefaultComponents())
8243                 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
8244         when(mAssistants.getDefaultFromConfig())
8245                 .thenReturn(newDefaultComponent);
8246         //User1: set different NAS
8247         when(mAssistants.getAllowedComponents(userId1))
8248                 .thenReturn(Arrays.asList(oldDefaultComponent));
8249         //User2: set to none
8250         when(mAssistants.getAllowedComponents(userId2))
8251                 .thenReturn(new ArrayList<>());
8252 
8253         when(mAssistants.hasUserSet(userId1)).thenReturn(true);
8254         when(mAssistants.hasUserSet(userId2)).thenReturn(true);
8255 
8256         service.migrateDefaultNAS();
8257         // user1's setting get reset
8258         verify(mAssistants, times(1)).setUserSet(userId1, false);
8259         verify(mAssistants, times(0)).setUserSet(eq(userId2), anyBoolean());
8260         assertTrue(service.isNASMigrationDone(userId2));
8261 
8262     }
8263 
8264     @Test
testNASSettingUpgrade_multiProfile()8265     public void testNASSettingUpgrade_multiProfile() throws RemoteException {
8266         ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1");
8267         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2");
8268         TestableNotificationManagerService service = spy(mService);
8269         int userId1 = 11;
8270         int userId2 = 12; //work profile
8271         setUsers(new int[]{userId1, userId2});
8272         when(mUm.isManagedProfile(userId2)).thenReturn(true);
8273         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2});
8274 
8275         setNASMigrationDone(false, userId1);
8276         setNASMigrationDone(false, userId2);
8277         when(mAssistants.getDefaultComponents())
8278                 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
8279         when(mAssistants.getDefaultFromConfig())
8280                 .thenReturn(newDefaultComponent);
8281         //Both profiles: set different NAS
8282         when(mAssistants.getAllowedComponents(userId1))
8283                 .thenReturn(Arrays.asList(oldDefaultComponent));
8284         when(mAssistants.getAllowedComponents(userId2))
8285                 .thenReturn(Arrays.asList(oldDefaultComponent));
8286 
8287         when(mAssistants.hasUserSet(userId1)).thenReturn(true);
8288         when(mAssistants.hasUserSet(userId2)).thenReturn(true);
8289 
8290         service.migrateDefaultNAS();
8291         assertFalse(service.isNASMigrationDone(userId1));
8292         assertFalse(service.isNASMigrationDone(userId2));
8293     }
8294 
8295 
8296 
8297     @Test
testNASSettingUpgrade_clearDataAfterMigrationIsDone()8298     public void testNASSettingUpgrade_clearDataAfterMigrationIsDone() throws RemoteException {
8299         ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component");
8300         TestableNotificationManagerService service = spy(mService);
8301         int userId = 12;
8302         setUsers(new int[]{userId});
8303         when(mAssistants.getDefaultComponents())
8304                 .thenReturn(new ArraySet<>(Arrays.asList(defaultComponent)));
8305         when(mAssistants.hasUserSet(userId)).thenReturn(true);
8306         setNASMigrationDone(true, userId);
8307 
8308         //Test User clear data
8309         ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
8310                 generateResetComponentValues();
8311         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
8312         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
8313         changes.put(true, new ArrayList(Arrays.asList(defaultComponent)));
8314         changes.put(false, new ArrayList());
8315         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
8316 
8317         //Clear data
8318         service.getBinderService().clearData("package", userId, false);
8319         //Test migrate flow again
8320         service.migrateDefaultNAS();
8321 
8322         //Migration should not happen again
8323         verify(mAssistants, times(0)).setUserSet(userId, false);
8324         verify(mAssistants, times(0)).clearDefaults();
8325         //resetDefaultAssistantsIfNecessary should only invoke once from readPolicyXml()
8326         verify(mAssistants, times(1)).resetDefaultAssistantsIfNecessary();
8327 
8328     }
8329 
setNASMigrationDone(boolean done, int userId)8330     private void setNASMigrationDone(boolean done, int userId) {
8331         Settings.Secure.putIntForUser(mContext.getContentResolver(),
8332                 Settings.Secure.NAS_SETTINGS_UPDATED, done ? 1 : 0, userId);
8333     }
8334 
setUsers(int[] userIds)8335     private void setUsers(int[] userIds) {
8336         List<UserInfo> users = new ArrayList<>();
8337         for (int id: userIds) {
8338             users.add(new UserInfo(id, String.valueOf(id), 0));
8339         }
8340         for (UserInfo user : users) {
8341             when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
8342         }
8343         when(mUm.getUsers()).thenReturn(users);
8344     }
8345 
8346     @Test
clearDefaultListenersPackageShouldEnableIt()8347     public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
8348         ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
8349                 generateResetComponentValues();
8350         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
8351         ComponentName deviceConfig = new ComponentName("device", "config");
8352         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
8353         changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
8354         changes.put(false, new ArrayList());
8355         when(mListeners.resetComponents(anyString(), anyInt()))
8356             .thenReturn(changes);
8357         mService.getBinderService().clearData("device", 0, false);
8358         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
8359                 eq("device"), eq(0), eq(false), eq(true));
8360     }
8361 
8362     @Test
clearDefaultDnDPackageShouldEnableIt()8363     public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
8364         ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
8365         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
8366         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
8367         mService.getBinderService().clearData("pkgName", 0, false);
8368         verify(mConditionProviders, times(1)).resetPackage(
8369                         eq("pkgName"), eq(0));
8370     }
8371 
8372     @Test
testFlagBubble()8373     public void testFlagBubble() throws RemoteException {
8374         setUpPrefsForBubbles(PKG, mUid,
8375                 true /* global */,
8376                 BUBBLE_PREFERENCE_ALL /* app */,
8377                 true /* channel */);
8378 
8379         NotificationRecord nr =
8380                 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
8381 
8382         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8383                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8384         waitForIdle();
8385 
8386         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8387         assertEquals(1, notifs.length);
8388         assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
8389         assertTrue(mService.getNotificationRecord(
8390                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8391     }
8392 
8393     @Test
testFlagBubble_noFlag_appNotAllowed()8394     public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
8395         setUpPrefsForBubbles(PKG, mUid,
8396                 true /* global */,
8397                 BUBBLE_PREFERENCE_NONE /* app */,
8398                 true /* channel */);
8399 
8400         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8401                         "testFlagBubble_noFlag_appNotAllowed");
8402 
8403         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8404                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8405         waitForIdle();
8406 
8407         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8408         assertEquals(1, notifs.length);
8409         assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
8410         assertFalse(mService.getNotificationRecord(
8411                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8412     }
8413 
8414     @Test
testFlagBubbleNotifs_noFlag_whenAppForeground()8415     public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
8416         setUpPrefsForBubbles(PKG, mUid,
8417                 true /* global */,
8418                 BUBBLE_PREFERENCE_ALL /* app */,
8419                 true /* channel */);
8420 
8421         // Notif with bubble metadata but not our other misc requirements
8422         Notification.Builder nb = new Notification.Builder(mContext,
8423                 mTestNotificationChannel.getId())
8424                 .setContentTitle("foo")
8425                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
8426                 .setBubbleMetadata(getBubbleMetadata());
8427         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
8428                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8429         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
8430 
8431         // Say we're foreground
8432         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
8433                 IMPORTANCE_FOREGROUND);
8434         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8435                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8436         waitForIdle();
8437 
8438         // if notif isn't configured properly it doesn't get to bubble just because app is
8439         // foreground.
8440         assertFalse(mService.getNotificationRecord(
8441                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8442     }
8443 
8444     @Test
testFlagBubbleNotifs_flag_messaging()8445     public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
8446         setUpPrefsForBubbles(PKG, mUid,
8447                 true /* global */,
8448                 BUBBLE_PREFERENCE_ALL /* app */,
8449                 true /* channel */);
8450 
8451         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8452                 "testFlagBubbleNotifs_flag_messaging");
8453 
8454         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8455                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8456         waitForIdle();
8457 
8458         // yes allowed, yes messaging, yes bubble
8459         assertTrue(mService.getNotificationRecord(
8460                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8461     }
8462 
8463     @Test
testFlagBubbleNotifs_noFlag_noShortcut()8464     public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException {
8465         setUpPrefsForBubbles(PKG, mUid,
8466                 true /* global */,
8467                 BUBBLE_PREFERENCE_ALL /* app */,
8468                 true /* channel */);
8469 
8470         Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false);
8471         nb.setShortcutId(null);
8472         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
8473                 null, mUid, 0,
8474                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8475 
8476         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
8477                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
8478         waitForIdle();
8479 
8480         // no shortcut no bubble
8481         assertFalse(mService.getNotificationRecord(
8482                 sbn.getKey()).getNotification().isBubbleNotification());
8483     }
8484 
8485     @Test
testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()8486     public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
8487         setUpPrefsForBubbles(PKG, mUid,
8488                 true /* global */,
8489                 BUBBLE_PREFERENCE_NONE /* app */,
8490                 true /* channel */);
8491 
8492         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8493                 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
8494 
8495         // Post the notification
8496         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8497                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8498         waitForIdle();
8499 
8500         // not allowed, no bubble
8501         assertFalse(mService.getNotificationRecord(
8502                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8503     }
8504 
8505     @Test
testFlagBubbleNotifs_noFlag_notBubble()8506     public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
8507         setUpPrefsForBubbles(PKG, mUid,
8508                 true /* global */,
8509                 BUBBLE_PREFERENCE_ALL /* app */,
8510                 true /* channel */);
8511 
8512         // Messaging notif WITHOUT bubble metadata
8513         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
8514                 null /* groupKey */, false /* isSummary */);
8515 
8516         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
8517                 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
8518                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8519         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
8520 
8521         // Post the notification
8522         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8523                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8524         waitForIdle();
8525 
8526         // no bubble metadata, no bubble
8527         assertFalse(mService.getNotificationRecord(
8528                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8529     }
8530 
8531     @Test
testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()8532     public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
8533         setUpPrefsForBubbles(PKG, mUid,
8534                 true /* global */,
8535                 BUBBLE_PREFERENCE_ALL /* app */,
8536                 false /* channel */);
8537 
8538         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8539                 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
8540         nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
8541 
8542         // Post the notification
8543         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8544                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8545         waitForIdle();
8546 
8547         // channel not allowed, no bubble
8548         assertFalse(mService.getNotificationRecord(
8549                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8550     }
8551 
8552     @Test
testCancelNotificationsFromApp_cancelsBubbles()8553     public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
8554         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
8555         nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
8556 
8557         // Post the notification
8558         mBinderService.enqueueNotificationWithTag(PKG, PKG,
8559                 "testAppCancelNotifications_cancelsBubbles",
8560                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
8561                 nrBubble.getSbn().getUserId());
8562         waitForIdle();
8563 
8564         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8565         assertEquals(1, notifs.length);
8566         assertEquals(1, mService.getNotificationRecordCount());
8567 
8568         mBinderService.cancelNotificationWithTag(PKG, PKG,
8569                 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
8570                 nrBubble.getSbn().getUserId());
8571         waitForIdle();
8572 
8573         StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
8574         assertEquals(0, notifs2.length);
8575         assertEquals(0, mService.getNotificationRecordCount());
8576     }
8577 
8578     @Test
testCancelAllNotificationsFromApp_cancelsBubble()8579     public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
8580         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8581         nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
8582         mService.addNotification(nr);
8583 
8584         mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
8585         waitForIdle();
8586 
8587         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8588         assertEquals(0, notifs.length);
8589         assertEquals(0, mService.getNotificationRecordCount());
8590     }
8591 
8592     @Test
testCancelAllNotificationsFromListener_ignoresBubbles()8593     public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
8594         final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
8595         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
8596         nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
8597 
8598         mService.addNotification(nrNormal);
8599         mService.addNotification(nrBubble);
8600 
8601         mService.getBinderService().cancelNotificationsFromListener(null, null);
8602         waitForIdle();
8603 
8604         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8605         assertEquals(1, notifs.length);
8606         assertEquals(1, mService.getNotificationRecordCount());
8607     }
8608 
8609     @Test
testCancelNotificationsFromListener_cancelsNonBubble()8610     public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception {
8611         // Add non-bubble notif
8612         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8613         mService.addNotification(nr);
8614 
8615         // Cancel via listener
8616         String[] keys = {nr.getSbn().getKey()};
8617         mService.getBinderService().cancelNotificationsFromListener(null, keys);
8618         waitForIdle();
8619 
8620         // Notif not active anymore
8621         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8622         assertEquals(0, notifs.length);
8623         assertEquals(0, mService.getNotificationRecordCount());
8624         // Cancel event is logged
8625         assertEquals(1, mNotificationRecordLogger.numCalls());
8626         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
8627             .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
8628     }
8629 
8630     @Test
testCancelNotificationsFromListener_suppressesBubble()8631     public void testCancelNotificationsFromListener_suppressesBubble() throws Exception {
8632         // Add bubble notif
8633         setUpPrefsForBubbles(PKG, mUid,
8634             true /* global */,
8635             BUBBLE_PREFERENCE_ALL /* app */,
8636             true /* channel */);
8637         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
8638 
8639         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8640             nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8641         waitForIdle();
8642 
8643         // Cancel via listener
8644         String[] keys = {nr.getSbn().getKey()};
8645         mService.getBinderService().cancelNotificationsFromListener(null, keys);
8646         waitForIdle();
8647 
8648         // Bubble notif active and suppressed
8649         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8650         assertEquals(1, notifs.length);
8651         assertEquals(1, mService.getNotificationRecordCount());
8652         assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed());
8653     }
8654 
8655     @Test
testCancelAllNotificationsFromStatusBar_ignoresBubble()8656     public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
8657         // GIVEN a notification bubble
8658         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8659         nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
8660         mService.addNotification(nr);
8661 
8662         // WHEN the status bar clears all notifications
8663         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
8664                 nr.getSbn().getUserId());
8665         waitForIdle();
8666 
8667         // THEN the bubble notification does not get removed
8668         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8669         assertEquals(1, notifs.length);
8670         assertEquals(1, mService.getNotificationRecordCount());
8671     }
8672 
8673 
8674     @Test
testGetAllowedAssistantAdjustments()8675     public void testGetAllowedAssistantAdjustments() throws Exception {
8676         List<String> adjustments = mBinderService.getAllowedAssistantAdjustments(null);
8677         assertNotNull(adjustments);
8678     }
8679 
8680     @Test
testAdjustRestrictedKey()8681     public void testAdjustRestrictedKey() throws Exception {
8682         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
8683         mService.addNotification(r);
8684         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
8685 
8686         when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
8687         when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
8688 
8689         Bundle signals = new Bundle();
8690         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
8691         signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
8692         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
8693                "", r.getUser().getIdentifier());
8694 
8695         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
8696         r.applyAdjustments();
8697 
8698         assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
8699         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
8700     }
8701 
8702     @Test
testAutomaticZenRuleValidation_policyFilterAgreement()8703     public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
8704         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8705                 .thenReturn(true);
8706         mService.setZenHelper(mock(ZenModeHelper.class));
8707         ComponentName owner = new ComponentName(mContext, this.getClass());
8708         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8709         boolean isEnabled = true;
8710         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8711                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
8712 
8713         try {
8714             mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
8715             fail("Zen policy only applies to priority only mode");
8716         } catch (IllegalArgumentException e) {
8717             // yay
8718         }
8719 
8720         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8721                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8722         mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
8723 
8724         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8725                 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
8726         mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
8727     }
8728 
8729     @Test
testAddAutomaticZenRule_systemCallTakesPackageFromOwner()8730     public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception {
8731         mService.isSystemUid = true;
8732         ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
8733         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8734                 .thenReturn(true);
8735         mService.setZenHelper(mockZenModeHelper);
8736         ComponentName owner = new ComponentName("android", "ProviderName");
8737         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8738         boolean isEnabled = true;
8739         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8740                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8741         mBinderService.addAutomaticZenRule(rule, "com.android.settings");
8742 
8743         // verify that zen mode helper gets passed in a package name of "android"
8744         verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(),
8745                 anyInt(), eq(true)); // system call counts as "is system or system ui"
8746     }
8747 
8748     @Test
testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner()8749     public void testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner() throws Exception {
8750         // The multi-user case: where the calling uid doesn't match the system uid, but the calling
8751         // *appid* is the system.
8752         mService.isSystemUid = false;
8753         mService.isSystemAppId = true;
8754         ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
8755         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8756                 .thenReturn(true);
8757         mService.setZenHelper(mockZenModeHelper);
8758         ComponentName owner = new ComponentName("android", "ProviderName");
8759         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8760         boolean isEnabled = true;
8761         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8762                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8763         mBinderService.addAutomaticZenRule(rule, "com.android.settings");
8764 
8765         // verify that zen mode helper gets passed in a package name of "android"
8766         verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(),
8767                 anyInt(),  eq(true));  // system call counts as "system or system ui"
8768     }
8769 
8770     @Test
testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg()8771     public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception {
8772         mService.isSystemUid = false;
8773         mService.isSystemAppId = false;
8774         ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
8775         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8776                 .thenReturn(true);
8777         mService.setZenHelper(mockZenModeHelper);
8778         ComponentName owner = new ComponentName("android", "ProviderName");
8779         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8780         boolean isEnabled = true;
8781         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8782                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8783         mBinderService.addAutomaticZenRule(rule, "another.package");
8784 
8785         // verify that zen mode helper gets passed in the package name from the arg, not the owner
8786         verify(mockZenModeHelper).addAutomaticZenRule(
8787                 eq("another.package"), eq(rule), anyString(), anyInt(),
8788                 eq(false));  // doesn't count as a system/systemui call
8789     }
8790 
8791     @Test
onZenModeChanged_sendsBroadcasts()8792     public void onZenModeChanged_sendsBroadcasts() throws Exception {
8793         when(mAmi.getCurrentUserId()).thenReturn(100);
8794         when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102});
8795         when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() {
8796             @Override
8797             public List<String> answer(InvocationOnMock invocation) {
8798                 int userId = invocation.getArgument(0);
8799                 switch (userId) {
8800                     case 100:
8801                         return Lists.newArrayList("a", "b", "c");
8802                     case 101:
8803                         return Lists.newArrayList();
8804                     case 102:
8805                         return Lists.newArrayList("b");
8806                     default:
8807                         throw new IllegalArgumentException(
8808                                 "Why would you ask for packages of userId " + userId + "?");
8809                 }
8810             }
8811         });
8812 
8813         mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
8814                 "testing!");
8815         waitForIdle();
8816 
8817         InOrder inOrder = inOrder(mContext);
8818         // Verify broadcasts for registered receivers
8819         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
8820                 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
8821                         Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null));
8822         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
8823                 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
8824                         Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null));
8825         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
8826                 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
8827                         Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null));
8828 
8829         // Verify broadcast for packages that manage DND.
8830         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8831                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags(
8832                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
8833         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8834                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
8835                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
8836         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8837                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags(
8838                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
8839         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8840                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
8841                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
8842     }
8843 
eqIntent(Intent wanted)8844     private static Intent eqIntent(Intent wanted) {
8845         return ArgumentMatchers.argThat(
8846                 new ArgumentMatcher<Intent>() {
8847                     @Override
8848                     public boolean matches(Intent argument) {
8849                         return wanted.filterEquals(argument)
8850                                 && wanted.getFlags() == argument.getFlags();
8851                     }
8852 
8853                     @Override
8854                     public String toString() {
8855                         return wanted.toString();
8856                     }
8857                 });
8858     }
8859 
8860     @Test
8861     public void testAreNotificationsEnabledForPackage() throws Exception {
8862         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
8863                 mUid);
8864 
8865         verify(mPermissionHelper).hasPermission(mUid);
8866     }
8867 
8868     @Test
8869     public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
8870         try {
8871             mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
8872                     mUid + UserHandle.PER_USER_RANGE);
8873             fail("Cannot call cross user without permission");
8874         } catch (SecurityException e) {
8875             // pass
8876         }
8877         verify(mPermissionHelper, never()).hasPermission(anyInt());
8878 
8879         // cross user, with permission, no problem
8880         enableInteractAcrossUsers();
8881         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
8882                 mUid + UserHandle.PER_USER_RANGE);
8883 
8884         verify(mPermissionHelper).hasPermission(mUid + UserHandle.PER_USER_RANGE);
8885     }
8886 
8887     @Test
8888     public void testAreNotificationsEnabledForPackage_viaInternalService() {
8889         mInternalService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid);
8890         verify(mPermissionHelper).hasPermission(mUid);
8891     }
8892 
8893     @Test
8894     public void testGetPackageImportance() throws Exception {
8895         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
8896         assertThat(mBinderService.getPackageImportance(mContext.getPackageName()))
8897                 .isEqualTo(IMPORTANCE_DEFAULT);
8898 
8899         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
8900         assertThat(mBinderService.getPackageImportance(mContext.getPackageName()))
8901                 .isEqualTo(IMPORTANCE_NONE);
8902     }
8903 
8904     @Test
8905     public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
8906         try {
8907             mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
8908                     mUid + UserHandle.PER_USER_RANGE);
8909             fail("Cannot call cross user without permission");
8910         } catch (SecurityException e) {
8911             // pass
8912         }
8913 
8914         // cross user, with permission, no problem
8915         enableInteractAcrossUsers();
8916         mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
8917                 mUid + UserHandle.PER_USER_RANGE);
8918     }
8919 
8920     private void enableInteractAcrossUsers() {
8921         TestablePermissions perms = mContext.getTestablePermissions();
8922         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
8923     }
8924 
8925     @Test
8926     public void testNotificationBubbleChanged_false() throws Exception {
8927         setUpPrefsForBubbles(PKG, mUid,
8928                 true /* global */,
8929                 BUBBLE_PREFERENCE_ALL /* app */,
8930                 true /* channel */);
8931 
8932         // Notif with bubble metadata
8933         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8934                 "testNotificationBubbleChanged_false");
8935 
8936         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8937                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8938         waitForIdle();
8939 
8940         // Reset as this is called when the notif is first sent
8941         reset(mListeners);
8942 
8943         // First we were a bubble
8944         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
8945         assertEquals(1, notifsBefore.length);
8946         assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
8947 
8948         // Notify we're not a bubble
8949         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
8950         waitForIdle();
8951 
8952         // Make sure we are not a bubble
8953         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
8954         assertEquals(1, notifsAfter.length);
8955         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
8956     }
8957 
8958     @Test
8959     public void testNotificationBubbleChanged_true() throws Exception {
8960         setUpPrefsForBubbles(PKG, mUid,
8961                 true /* global */,
8962                 BUBBLE_PREFERENCE_ALL /* app */,
8963                 true /* channel */);
8964 
8965         // Notif that is not a bubble
8966         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
8967                 1, null, false);
8968         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8969                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8970         waitForIdle();
8971 
8972         // Would be a normal notification because wouldn't have met requirements to bubble
8973         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
8974         assertEquals(1, notifsBefore.length);
8975         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
8976 
8977         // Update the notification to be message style / meet bubble requirements
8978         NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8979                 nr.getSbn().getTag());
8980         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
8981                 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
8982         waitForIdle();
8983 
8984         // Reset as this is called when the notif is first sent
8985         reset(mListeners);
8986 
8987         // Notify we are now a bubble
8988         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
8989         waitForIdle();
8990 
8991         // Make sure we are a bubble
8992         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
8993         assertEquals(1, notifsAfter.length);
8994         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
8995     }
8996 
8997     @Test
8998     public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
8999         setUpPrefsForBubbles(PKG, mUid,
9000                 true /* global */,
9001                 BUBBLE_PREFERENCE_ALL /* app */,
9002                 true /* channel */);
9003 
9004         // Notif that is not a bubble
9005         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
9006         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9007                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9008         waitForIdle();
9009 
9010         // Reset as this is called when the notif is first sent
9011         reset(mListeners);
9012 
9013         // Would be a normal notification because wouldn't have met requirements to bubble
9014         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9015         assertEquals(1, notifsBefore.length);
9016         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
9017 
9018         // Notify we are now a bubble
9019         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
9020         waitForIdle();
9021 
9022         // We still wouldn't be a bubble because the notification didn't meet requirements
9023         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9024         assertEquals(1, notifsAfter.length);
9025         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
9026     }
9027 
9028     @Test
9029     public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
9030         setUpPrefsForBubbles(PKG, mUid,
9031                 true /* global */,
9032                 BUBBLE_PREFERENCE_ALL /* app */,
9033                 true /* channel */);
9034 
9035         // Notif with bubble metadata
9036         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9037                 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
9038 
9039         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9040                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9041         waitForIdle();
9042         // Flag shouldn't be modified
9043         NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
9044         assertFalse(recordToCheck.isFlagBubbleRemoved());
9045 
9046         // Notify we're not a bubble
9047         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
9048         waitForIdle();
9049         // Flag should be modified
9050         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
9051         assertTrue(recordToCheck.isFlagBubbleRemoved());
9052 
9053 
9054         // Update the notif
9055         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9056                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9057         waitForIdle();
9058         // And the flag is reset
9059         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
9060         assertFalse(recordToCheck.isFlagBubbleRemoved());
9061     }
9062 
9063     @Test
9064     public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
9065         setUpPrefsForBubbles(PKG, mUid,
9066                 true /* global */,
9067                 BUBBLE_PREFERENCE_ALL /* app */,
9068                 true /* channel */);
9069 
9070         // Notif with bubble metadata
9071         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9072                 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
9073 
9074         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9075                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9076         waitForIdle();
9077         // Flag shouldn't be modified
9078         NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
9079         assertFalse(recordToCheck.isFlagBubbleRemoved());
9080 
9081         // Notify we're not a bubble
9082         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
9083         waitForIdle();
9084         // Flag should be modified
9085         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
9086         assertTrue(recordToCheck.isFlagBubbleRemoved());
9087 
9088         // Notify we are a bubble
9089         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
9090         waitForIdle();
9091         // And the flag is reset
9092         assertFalse(recordToCheck.isFlagBubbleRemoved());
9093     }
9094 
9095     @Test
9096     public void testOnBubbleMetadataFlagChanged() throws Exception {
9097         setUpPrefsForBubbles(PKG, mUid,
9098                 true /* global */,
9099                 BUBBLE_PREFERENCE_ALL /* app */,
9100                 true /* channel */);
9101 
9102         // Post a bubble notification
9103         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
9104         // Set this so that the bubble can be suppressed
9105         nr.getNotification().getBubbleMetadata().setFlags(
9106                 Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE);
9107         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9108                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9109         waitForIdle();
9110 
9111         // Check the flags
9112         Notification n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
9113         assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
9114         assertFalse(n.getBubbleMetadata().getAutoExpandBubble());
9115         assertFalse(n.getBubbleMetadata().isBubbleSuppressed());
9116         assertTrue(n.getBubbleMetadata().isBubbleSuppressable());
9117 
9118         // Reset as this is called when the notif is first sent
9119         reset(mListeners);
9120 
9121         // Test: change the flags
9122         int flags = Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE;
9123         flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE;
9124         flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
9125         flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE;
9126         mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), flags);
9127         waitForIdle();
9128 
9129         // Check
9130         n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
9131         assertEquals(flags, n.getBubbleMetadata().getFlags());
9132 
9133         // Reset to check again
9134         reset(mListeners);
9135 
9136         // Test: clear flags
9137         mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), 0);
9138         waitForIdle();
9139 
9140         // Check
9141         n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
9142         assertEquals(0, n.getBubbleMetadata().getFlags());
9143     }
9144 
9145     @Test
9146     public void testOnBubbleMetadataChangedToSuppressNotification_soundStopped()
9147             throws RemoteException {
9148         IRingtonePlayer mockPlayer = mock(IRingtonePlayer.class);
9149         when(mAudioManager.getRingtonePlayer()).thenReturn(mockPlayer);
9150         // Set up volume to be above 0 for the sound to actually play
9151         when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
9152 
9153         setUpPrefsForBubbles(PKG, mUid,
9154                 true /* global */,
9155                 BUBBLE_PREFERENCE_ALL /* app */,
9156                 true /* channel */);
9157 
9158         // Post a bubble notification
9159         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
9160         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9161                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9162         waitForIdle();
9163 
9164         // Test: suppress notification via bubble metadata update
9165         mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(),
9166                 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
9167         waitForIdle();
9168 
9169         // Check audio is stopped
9170         verify(mockPlayer).stopAsync();
9171     }
9172 
9173     @Test
9174     public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
9175         int userId = UserManager.isHeadlessSystemUserMode()
9176                 ? UserHandle.getUserId(UID_HEADLESS)
9177                 : USER_SYSTEM;
9178 
9179         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId);
9180         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
9181                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9182         waitForIdle();
9183 
9184         // A notification exists for the given record
9185         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9186         assertEquals(1, notifsBefore.length);
9187 
9188         reset(mPackageManager);
9189 
9190         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9191 
9192         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9193                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9194                 nr.getSbn().getUid());
9195 
9196         // Grant permission called for the UID of SystemUI under the target user ID
9197         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9198                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
9199                 anyInt(), eq(nr.getSbn().getUserId()));
9200     }
9201 
9202     @Test
9203     public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
9204         int userId = UserManager.isHeadlessSystemUserMode()
9205                 ? UserHandle.getUserId(UID_HEADLESS)
9206                 : USER_SYSTEM;
9207 
9208         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId);
9209         waitForIdle();
9210 
9211         // No notifications exist for the given record
9212         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9213         assertEquals(0, notifsBefore.length);
9214 
9215         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9216 
9217         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9218                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9219                 nr.getSbn().getUid());
9220 
9221         // Grant permission still called if no NotificationRecord exists for the given key
9222         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9223                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
9224                 anyInt(), eq(nr.getSbn().getUserId()));
9225     }
9226 
9227     @Test
9228     public void testGrantInlineReplyUriPermission_userAll() throws Exception {
9229         // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
9230         NotificationRecord nr =
9231                 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
9232         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
9233                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9234         waitForIdle();
9235 
9236         // A notification exists for the given record
9237         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9238         assertEquals(1, notifsBefore.length);
9239 
9240         reset(mPackageManager);
9241 
9242         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9243 
9244         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9245                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9246                 nr.getSbn().getUid());
9247 
9248         // Target user for the grant is USER_ALL instead of USER_SYSTEM
9249         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9250                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
9251                 anyInt(), UserManager.isHeadlessSystemUserMode()
9252                         ? eq(UserHandle.getUserId(UID_HEADLESS))
9253                         : eq(USER_SYSTEM));
9254     }
9255 
9256     @Test
9257     public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
9258         // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
9259         int otherUserId = 11;
9260         NotificationRecord nr =
9261                 generateNotificationRecord(mTestNotificationChannel, otherUserId);
9262         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
9263                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9264         waitForIdle();
9265 
9266         // A notification exists for the given record
9267         List<StatusBarNotification> notifsBefore =
9268                 mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList();
9269         assertEquals(1, notifsBefore.size());
9270 
9271         reset(mPackageManager);
9272 
9273         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9274 
9275         int uid = 0; // sysui on primary user
9276         int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
9277         String sysuiPackage = "sysui";
9278         final String[] sysuiPackages = new String[] { sysuiPackage };
9279         when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
9280 
9281         // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
9282         // time this is called
9283         when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
9284                 .thenReturn(otherUserUid);
9285 
9286         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9287                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
9288 
9289         // Target user for the grant is USER_ALL instead of USER_SYSTEM
9290         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9291                 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
9292                 eq(otherUserId));
9293     }
9294 
9295     @Test
9296     public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
9297         int userId = UserManager.isHeadlessSystemUserMode()
9298                 ? UserHandle.getUserId(UID_HEADLESS)
9299                 : USER_SYSTEM;
9300 
9301         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId);
9302         reset(mPackageManager);
9303 
9304         Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9305         Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
9306 
9307         // create an inline record with two uris in it
9308         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9309                 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9310                 nr.getSbn().getUid());
9311         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9312                 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9313                 nr.getSbn().getUid());
9314 
9315         InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
9316         assertNotNull(record); // record exists
9317         assertEquals(record.getUris().size(), 2); // record has two uris in it
9318 
9319         mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
9320                 nr.getSbn().getUid());
9321 
9322         // permissionOwner destroyed
9323         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
9324                 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
9325     }
9326 
9327 
9328     @Test
9329     public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
9330         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
9331         reset(mPackageManager);
9332 
9333         mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
9334                 nr.getSbn().getUid());
9335 
9336         // no permissionOwner destroyed
9337         verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
9338                 any(), eq(null), eq(~0), eq(nr.getUserId()));
9339     }
9340 
9341     @Test
9342     public void testClearInlineReplyUriPermission_userAll() throws Exception {
9343         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
9344                 UserHandle.USER_ALL);
9345         reset(mPackageManager);
9346 
9347         Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9348 
9349         // create an inline record a uri in it
9350         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9351                 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9352                 nr.getSbn().getUid());
9353 
9354         InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
9355         assertNotNull(record); // record exists
9356 
9357         mService.mNotificationDelegate.clearInlineReplyUriPermissions(
9358                 nr.getKey(), nr.getSbn().getUid());
9359 
9360         // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
9361         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
9362                 eq(record.getPermissionOwner()), eq(null), eq(~0),
9363                 UserManager.isHeadlessSystemUserMode()
9364                         ? eq(UserHandle.getUserId(UID_HEADLESS))
9365                         : eq(USER_SYSTEM));
9366     }
9367 
9368     @Test
9369     public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
9370         setUpPrefsForBubbles(PKG, mUid,
9371                 true /* global */,
9372                 BUBBLE_PREFERENCE_ALL /* app */,
9373                 true /* channel */);
9374 
9375         // And we are low ram
9376         when(mActivityManager.isLowRamDevice()).thenReturn(true);
9377 
9378         // Notification that would typically bubble
9379         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9380                 "testNotificationBubbles_disabled_lowRamDevice");
9381         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9382                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9383         waitForIdle();
9384 
9385         // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
9386         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9387         assertEquals(1, notifsAfter.length);
9388         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
9389     }
9390 
9391     @Test
9392     public void testRemoveLargeRemoteViews() throws Exception {
9393         int removeSize = mContext.getResources().getInteger(
9394                 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
9395 
9396         RemoteViews rv = mock(RemoteViews.class);
9397         when(rv.estimateMemoryUsage()).thenReturn(removeSize);
9398         when(rv.clone()).thenReturn(rv);
9399         RemoteViews rv1 = mock(RemoteViews.class);
9400         when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
9401         when(rv1.clone()).thenReturn(rv1);
9402         RemoteViews rv2 = mock(RemoteViews.class);
9403         when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
9404         when(rv2.clone()).thenReturn(rv2);
9405         RemoteViews rv3 = mock(RemoteViews.class);
9406         when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
9407         when(rv3.clone()).thenReturn(rv3);
9408         RemoteViews rv4 = mock(RemoteViews.class);
9409         when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
9410         when(rv4.clone()).thenReturn(rv4);
9411         // note: different!
9412         RemoteViews rv5 = mock(RemoteViews.class);
9413         when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
9414         when(rv5.clone()).thenReturn(rv5);
9415 
9416         Notification np = new Notification.Builder(mContext, "test")
9417                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
9418                 .setContentText("test")
9419                 .setCustomContentView(rv)
9420                 .setCustomBigContentView(rv1)
9421                 .setCustomHeadsUpContentView(rv2)
9422                 .build();
9423         Notification n = new Notification.Builder(mContext, "test")
9424                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
9425                 .setContentText("test")
9426                 .setCustomContentView(rv3)
9427                 .setCustomBigContentView(rv4)
9428                 .setCustomHeadsUpContentView(rv5)
9429                 .setPublicVersion(np)
9430                 .build();
9431 
9432         assertNotNull(np.contentView);
9433         assertNotNull(np.bigContentView);
9434         assertNotNull(np.headsUpContentView);
9435 
9436         assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
9437         assertNotNull(n.publicVersion.contentView);
9438         assertNotNull(n.publicVersion.bigContentView);
9439         assertNotNull(n.publicVersion.headsUpContentView);
9440 
9441         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
9442 
9443         assertNull(n.contentView);
9444         assertNull(n.bigContentView);
9445         assertNotNull(n.headsUpContentView);
9446         assertNull(n.publicVersion.contentView);
9447         assertNull(n.publicVersion.bigContentView);
9448         assertNull(n.publicVersion.headsUpContentView);
9449 
9450         verify(mUsageStats, times(5)).registerImageRemoved(PKG);
9451     }
9452 
9453     @Test
9454     public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
9455             throws Exception {
9456         setUpPrefsForBubbles(PKG, mUid,
9457                 true /* global */,
9458                 BUBBLE_PREFERENCE_ALL /* app */,
9459                 true /* channel */);
9460 
9461         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9462                 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
9463         // Modify metadata flags
9464         nr.getSbn().getNotification().getBubbleMetadata().setFlags(
9465                 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
9466                         | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
9467 
9468         // Ensure we're not foreground
9469         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
9470                 IMPORTANCE_VISIBLE);
9471 
9472         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9473                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9474         waitForIdle();
9475 
9476         // yes allowed, yes messaging, yes bubble
9477         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9478         assertTrue(notif.isBubbleNotification());
9479 
9480         // The flag should have failed since we're not foreground
9481         assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
9482     }
9483 
9484     @Test
9485     public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
9486             throws RemoteException {
9487         setUpPrefsForBubbles(PKG, mUid,
9488                 true /* global */,
9489                 BUBBLE_PREFERENCE_ALL /* app */,
9490                 true /* channel */);
9491 
9492         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9493                 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
9494         // Modify metadata flags
9495         nr.getSbn().getNotification().getBubbleMetadata().setFlags(
9496                 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
9497                         | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
9498 
9499         // Ensure we are in the foreground
9500         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
9501                 IMPORTANCE_FOREGROUND);
9502 
9503         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9504                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9505         waitForIdle();
9506 
9507         // yes allowed, yes messaging, yes bubble
9508         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9509         assertTrue(notif.isBubbleNotification());
9510 
9511         // Our flags should have passed since we are foreground
9512         assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
9513         assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
9514     }
9515 
9516     @Test
9517     public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
9518             throws RemoteException {
9519         setUpPrefsForBubbles(PKG, mUid,
9520                 true /* global */,
9521                 BUBBLE_PREFERENCE_ALL /* app */,
9522                 true /* channel */);
9523 
9524         ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
9525                 ArgumentCaptor.forClass(LauncherApps.Callback.class);
9526 
9527         // Messaging notification with shortcut info
9528         Notification.BubbleMetadata metadata =
9529                 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build();
9530         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9531                 null /* groupKey */, false /* isSummary */);
9532         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
9533         nb.setBubbleMetadata(metadata);
9534         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
9535                 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
9536         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9537 
9538         // Test: Send the bubble notification
9539         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9540                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9541         waitForIdle();
9542 
9543         // Verify:
9544 
9545         // Make sure we register the callback for shortcut changes
9546         verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
9547 
9548         // yes allowed, yes messaging w/shortcut, yes bubble
9549         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9550         assertTrue(notif.isBubbleNotification());
9551 
9552         // Make sure the shortcut is cached.
9553         verify(mShortcutServiceInternal).cacheShortcuts(
9554                 anyInt(), any(), eq(PKG), eq(singletonList(VALID_CONVO_SHORTCUT_ID)),
9555                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
9556 
9557         // Test: Remove the shortcut
9558         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
9559         launcherAppsCallback.getValue().onShortcutsChanged(PKG, emptyList(),
9560                 UserHandle.getUserHandleForUid(mUid));
9561         waitForIdle();
9562 
9563         // Verify:
9564 
9565         // Make sure callback is unregistered
9566         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
9567 
9568         // We're no longer a bubble
9569         NotificationRecord notif2 = mService.getNotificationRecord(
9570                 nr.getSbn().getKey());
9571         assertNull(notif2.getShortcutInfo());
9572         assertFalse(notif2.getNotification().isBubbleNotification());
9573     }
9574 
9575     @Test
9576     public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
9577             throws RemoteException {
9578         final String shortcutId = "someshortcutId";
9579         setUpPrefsForBubbles(PKG, mUid,
9580                 true /* global */,
9581                 BUBBLE_PREFERENCE_ALL /* app */,
9582                 true /* channel */);
9583 
9584         ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
9585                 ArgumentCaptor.forClass(LauncherApps.Callback.class);
9586 
9587         // Messaging notification with shortcut info
9588         Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
9589                 shortcutId).build();
9590         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9591                 null /* groupKey */, false /* isSummary */);
9592         nb.setShortcutId(shortcutId);
9593         nb.setBubbleMetadata(metadata);
9594         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
9595                 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
9596         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9597 
9598         // Pretend the shortcut exists
9599         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
9600         ShortcutInfo info = mock(ShortcutInfo.class);
9601         when(info.getPackage()).thenReturn(PKG);
9602         when(info.getId()).thenReturn(shortcutId);
9603         when(info.getUserId()).thenReturn(USER_SYSTEM);
9604         when(info.isLongLived()).thenReturn(true);
9605         when(info.isEnabled()).thenReturn(true);
9606         shortcutInfos.add(info);
9607         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
9608         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
9609                 anyString(), anyInt(), any())).thenReturn(true);
9610 
9611         // Test: Send the bubble notification
9612         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9613                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9614         waitForIdle();
9615 
9616         // Verify:
9617 
9618         // Make sure we register the callback for shortcut changes
9619         verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
9620 
9621         // yes allowed, yes messaging w/shortcut, yes bubble
9622         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9623         assertTrue(notif.isBubbleNotification());
9624 
9625         // Make sure the shortcut is cached.
9626         verify(mShortcutServiceInternal).cacheShortcuts(
9627                 anyInt(), any(), eq(PKG), eq(singletonList(shortcutId)),
9628                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
9629 
9630         // Test: Remove the notification
9631         mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9632                 nr.getSbn().getId(), nr.getSbn().getUserId());
9633         waitForIdle();
9634 
9635         // Verify:
9636 
9637         // Make sure callback is unregistered
9638         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
9639     }
9640 
9641     @Test
9642     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
9643             throws Exception {
9644         setUpPrefsForBubbles(PKG, mUid,
9645                 true /* global */,
9646                 BUBBLE_PREFERENCE_ALL /* app */,
9647                 true /* channel */);
9648 
9649         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
9650                 true /* summaryAutoCancel */);
9651 
9652         // Dismiss summary
9653         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
9654                 true);
9655         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
9656                 nrSummary.getUserId(), nrSummary.getKey(),
9657                 NotificationStats.DISMISSAL_SHADE,
9658                 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
9659         waitForIdle();
9660 
9661         // The bubble should still exist
9662         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9663         assertEquals(1, notifsAfter.length);
9664     }
9665 
9666     @Test
9667     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
9668             throws Exception {
9669         setUpPrefsForBubbles(PKG, mUid,
9670                 true /* global */,
9671                 BUBBLE_PREFERENCE_ALL /* app */,
9672                 true /* channel */);
9673 
9674         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
9675                 true /* summaryAutoCancel */);
9676 
9677         // Click summary
9678         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
9679                 true);
9680         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
9681                 nrSummary.getKey(), nv);
9682         waitForIdle();
9683 
9684         // The bubble should still exist
9685         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9686         assertEquals(1, notifsAfter.length);
9687 
9688         // Check we got the click log and associated dismissal logs
9689         assertEquals(6, mNotificationRecordLogger.numCalls());
9690         // Skip the notification-creation logs
9691         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
9692                 mNotificationRecordLogger.event(3));
9693         assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
9694                 mNotificationRecordLogger.event(4));
9695         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
9696                         .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
9697                 mNotificationRecordLogger.event(5));
9698     }
9699 
9700     @Test
9701     public void testNotificationBubbles_bubbleStays_whenClicked()
9702             throws Exception {
9703         setUpPrefsForBubbles(PKG, mUid,
9704                 true /* global */,
9705                 BUBBLE_PREFERENCE_ALL /* app */,
9706                 true /* channel */);
9707 
9708         // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
9709         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
9710         nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
9711         mService.addNotification(nr);
9712 
9713         // WHEN we click the notification
9714         final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
9715         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
9716                 nr.getKey(), nv);
9717         waitForIdle();
9718 
9719         // THEN the bubble should still exist
9720         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9721         assertEquals(1, notifsAfter.length);
9722 
9723         // Check we got the click log
9724         assertEquals(1, mNotificationRecordLogger.numCalls());
9725         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
9726                 mNotificationRecordLogger.event(0));
9727     }
9728 
9729     /**
9730      * When something is bubble'd and the bubble is dismissed, but the notification is still
9731      * visible, clicking on the notification shouldn't auto-cancel it because clicking on
9732      * it will produce a bubble.
9733      */
9734     @Test
9735     public void testNotificationBubbles_bubbleStays_whenClicked_afterBubbleDismissed()
9736             throws Exception {
9737         setUpPrefsForBubbles(PKG, mUid,
9738                 true /* global */,
9739                 BUBBLE_PREFERENCE_ALL /* app */,
9740                 true /* channel */);
9741 
9742         // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
9743         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
9744         nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
9745         nr.setAllowBubble(true);
9746         mService.addNotification(nr);
9747 
9748         // And the bubble is dismissed
9749         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(),
9750                 false /* isBubble */, 0 /* bubbleFlags */);
9751         waitForIdle();
9752         assertTrue(nr.isFlagBubbleRemoved());
9753 
9754         // WHEN we click the notification
9755         final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
9756         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
9757                 nr.getKey(), nv);
9758         waitForIdle();
9759 
9760         // THEN the bubble should still exist
9761         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9762         assertEquals(1, notifsAfter.length);
9763 
9764         // Check we got the click log
9765         assertEquals(1, mNotificationRecordLogger.numCalls());
9766         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
9767                 mNotificationRecordLogger.event(0));
9768     }
9769 
9770     @Test
9771     public void testLoadDefaultApprovedServices_emptyResources() {
9772         TestableResources tr = mContext.getOrCreateTestableResources();
9773         tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
9774         tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
9775         tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
9776         setDefaultAssistantInDeviceConfig("");
9777 
9778         mService.loadDefaultApprovedServices(USER_SYSTEM);
9779 
9780         verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
9781         verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
9782         verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
9783     }
9784 
9785     @Test
9786     public void testLoadDefaultApprovedServices_dnd() {
9787         TestableResources tr = mContext.getOrCreateTestableResources();
9788         tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
9789         when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
9790                 .thenReturn(new ArraySet<>());
9791 
9792         mService.loadDefaultApprovedServices(USER_SYSTEM);
9793 
9794         verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
9795     }
9796 
9797     // TODO: add tests for the rest of the non-empty cases
9798 
9799     @Test
9800     public void testOnUnlockUser() {
9801         UserInfo ui = new UserInfo();
9802         ui.id = 10;
9803         mService.onUserUnlocked(new TargetUser(ui));
9804         waitForIdle();
9805 
9806         verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
9807     }
9808 
9809     @Test
9810     public void testOnStopUser() {
9811         UserInfo ui = new UserInfo();
9812         ui.id = 10;
9813         mService.onUserStopping(new TargetUser(ui));
9814         waitForIdle();
9815 
9816         verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
9817     }
9818 
9819     @Test
9820     public void testHandleOnPackageChanged() {
9821         String[] pkgs = new String[] {PKG, PKG_N_MR1};
9822         int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
9823 
9824         mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
9825 
9826         verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
9827 
9828         mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
9829 
9830         verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
9831         verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
9832     }
9833 
9834     @Test
9835     public void testNotificationHistory_addNoisyNotification() throws Exception {
9836         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
9837                 null /* tvExtender */);
9838         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9839                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9840         waitForIdle();
9841 
9842         verify(mHistoryManager, times(1)).addNotification(any());
9843     }
9844 
9845     @Test
9846     public void createConversationNotificationChannel() throws Exception {
9847         int userId = UserManager.isHeadlessSystemUserMode()
9848                 ? UserHandle.getUserId(UID_HEADLESS)
9849                 : USER_SYSTEM;
9850 
9851         NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
9852         original.setAllowBubbles(!original.canBubble());
9853         original.setShowBadge(!original.canShowBadge());
9854 
9855         Parcel parcel = Parcel.obtain();
9856         original.writeToParcel(parcel, 0);
9857         parcel.setDataPosition(0);
9858         NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
9859         assertEquals(original, orig);
9860         assertFalse(TextUtils.isEmpty(orig.getName()));
9861 
9862         mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
9863                 orig)));
9864 
9865         mBinderService.createConversationNotificationChannelForPackage(
9866                 PKG, mUid, orig, "friend");
9867 
9868         NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
9869                 PKG, userId, PKG, original.getId(), false, "friend");
9870 
9871         assertEquals(original.getName(), friendChannel.getName());
9872         assertEquals(original.getId(), friendChannel.getParentChannelId());
9873         assertEquals("friend", friendChannel.getConversationId());
9874         assertEquals(null, original.getConversationId());
9875         assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
9876         assertFalse(friendChannel.canBubble()); // can't be modified by app
9877         assertFalse(original.getId().equals(friendChannel.getId()));
9878         assertNotNull(friendChannel.getId());
9879     }
9880 
9881     @Test
9882     public void testCorrectCategory_systemOn_appCannotTurnOff() {
9883         int requested = 0;
9884         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9885 
9886         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9887                 system);
9888 
9889         assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
9890     }
9891 
9892     @Test
9893     public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
9894         int requested = PRIORITY_CATEGORY_CALLS;
9895         int system = PRIORITY_CATEGORY_CALLS;
9896 
9897         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9898                 system);
9899 
9900         assertEquals(PRIORITY_CATEGORY_CALLS, actual);
9901     }
9902 
9903     @Test
9904     public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
9905         int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9906         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9907 
9908         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9909                 system);
9910 
9911         assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
9912     }
9913 
9914     @Test
9915     public void testCorrectCategory_systemOff_appCannotTurnOn() {
9916         int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9917         int system = PRIORITY_CATEGORY_CALLS;
9918 
9919         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9920                 system);
9921 
9922         assertEquals(PRIORITY_CATEGORY_CALLS, actual);
9923     }
9924 
9925     @Test
9926     public void testGetConversationsForPackage_hasShortcut() throws Exception {
9927         mService.setPreferencesHelper(mPreferencesHelper);
9928         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
9929         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
9930         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
9931         channel1.setConversationId("parent1", "convo 1");
9932         convo1.setNotificationChannel(channel1);
9933         convos.add(convo1);
9934 
9935         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
9936         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
9937         channel2.setConversationId("parent1", "convo 2");
9938         convo2.setNotificationChannel(channel2);
9939         convos.add(convo2);
9940         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
9941 
9942         ShortcutInfo si = mock(ShortcutInfo.class);
9943         when(si.getPackage()).thenReturn(PKG_P);
9944         when(si.getId()).thenReturn("convo");
9945         when(si.getUserId()).thenReturn(USER_SYSTEM);
9946         when(si.getLabel()).thenReturn("Hello");
9947         when(si.isLongLived()).thenReturn(true);
9948         when(si.isEnabled()).thenReturn(true);
9949         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
9950         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
9951                 anyString(), anyInt(), any())).thenReturn(true);
9952 
9953         List<ConversationChannelWrapper> conversations =
9954                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9955         assertEquals(si, conversations.get(0).getShortcutInfo());
9956         assertEquals(si, conversations.get(1).getShortcutInfo());
9957 
9958         // Returns null shortcuts when locked.
9959         when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false);
9960         conversations =
9961                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9962         assertThat(conversations.get(0).getShortcutInfo()).isNull();
9963         assertThat(conversations.get(1).getShortcutInfo()).isNull();
9964     }
9965 
9966     @Test
9967     public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
9968         mService.setPreferencesHelper(mPreferencesHelper);
9969         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
9970         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
9971         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
9972         channel1.setConversationId("parent1", "convo 1");
9973         convo1.setNotificationChannel(channel1);
9974         convos.add(convo1);
9975 
9976         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
9977         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
9978         channel2.setConversationId("parent1", "convo 2");
9979         convo2.setNotificationChannel(channel2);
9980         convos.add(convo2);
9981         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
9982 
9983         ShortcutInfo si = mock(ShortcutInfo.class);
9984         when(si.getPackage()).thenReturn(PKG_P);
9985         when(si.getId()).thenReturn("convo");
9986         when(si.getUserId()).thenReturn(USER_SYSTEM);
9987         when(si.getLabel()).thenReturn("Hello");
9988         when(si.isLongLived()).thenReturn(false);
9989         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
9990 
9991         List<ConversationChannelWrapper> conversations =
9992                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9993         assertNull(conversations.get(0).getShortcutInfo());
9994         assertNull(conversations.get(1).getShortcutInfo());
9995     }
9996 
9997     @Test
9998     public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
9999         mService.setPreferencesHelper(mPreferencesHelper);
10000         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
10001         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
10002         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
10003         channel1.setConversationId("parent1", "convo 1");
10004         convo1.setNotificationChannel(channel1);
10005         convos.add(convo1);
10006 
10007         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
10008         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
10009         channel2.setConversationId("parent1", "convo 2");
10010         convo2.setNotificationChannel(channel2);
10011         convos.add(convo2);
10012         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
10013         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
10014 
10015         List<ConversationChannelWrapper> conversations =
10016                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
10017         assertNull(conversations.get(0).getShortcutInfo());
10018         assertNull(conversations.get(1).getShortcutInfo());
10019     }
10020 
10021     @Test
10022     public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
10023         mService.setShortcutHelper(null);
10024         NotificationRecord nr =
10025                 generateMessageBubbleNotifRecord(mTestNotificationChannel,
10026                         "testShortcutHelperNull_doesntCrashEnqueue");
10027         try {
10028             mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
10029                     nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10030             waitForIdle();
10031         } catch (Exception e) {
10032             fail(e.getMessage());
10033         }
10034     }
10035 
10036     @Test
10037     public void testRecordMessages_invalidMsg() throws RemoteException {
10038         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
10039                 null /* groupKey */, false /* isSummary */);
10040         nb.setShortcutId(null);
10041         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
10042                 "testRecordMessages_invalidMsg", mUid, 0, nb.build(),
10043                 UserHandle.getUserHandleForUid(mUid), null, 0);
10044         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10045 
10046         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
10047         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
10048                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10049         waitForIdle();
10050 
10051         assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
10052     }
10053 
10054     @Test
10055     public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException {
10056         Notification.Builder nb = new Notification.Builder(mContext,
10057                 mTestNotificationChannel.getId())
10058                 .setContentTitle("foo")
10059                 .setShortcutId(null)
10060                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10061                 .setCategory(Notification.CATEGORY_MESSAGE);
10062         StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1,
10063                 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(),
10064                 UserHandle.getUserHandleForUid(mUid), null, 0);
10065         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10066 
10067         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
10068         mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(),
10069                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10070         waitForIdle();
10071 
10072         // PKG_O is allowed to be in conversation space b/c of override in
10073         // TestableNotificationManagerService
10074         assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid));
10075     }
10076 
10077     @Test
10078     public void testRecordMessages_validMsg() throws RemoteException {
10079         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
10080                 null /* groupKey */, false /* isSummary */);
10081         nb.setShortcutId(null);
10082         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
10083                 "testRecordMessages_validMsg", mUid, 0, nb.build(),
10084                 UserHandle.getUserHandleForUid(mUid), null, 0);
10085         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10086 
10087         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
10088                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10089         waitForIdle();
10090 
10091         assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
10092 
10093         nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
10094                 "testRecordMessages_validMsg");
10095 
10096         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
10097                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10098         waitForIdle();
10099 
10100         assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid));
10101     }
10102 
10103     @Test
10104     public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException {
10105         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
10106                 "testRecordMessages_invalidMsg_afterValidMsg_1");
10107         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
10108                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10109         waitForIdle();
10110         assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation());
10111 
10112         mBinderService.cancelAllNotifications(PKG, mUid);
10113         waitForIdle();
10114 
10115         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
10116                 null /* groupKey */, false /* isSummary */);
10117         nb.setShortcutId(null);
10118         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
10119                 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
10120                 UserHandle.getUserHandleForUid(mUid), null, 0);
10121          nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10122 
10123         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
10124                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
10125         waitForIdle();
10126 
10127         assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation());
10128     }
10129 
10130     @Test
10131     public void testCanPostFgsWhenOverLimit() throws RemoteException {
10132         when(mAmi.applyForegroundServiceNotification(
10133                 any(), anyString(), anyInt(), anyString(), anyInt()))
10134                 .thenReturn(SHOW_IMMEDIATELY);
10135         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
10136             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
10137                     i, null, false).getSbn();
10138             mBinderService.enqueueNotificationWithTag(PKG, PKG,
10139                     "testCanPostFgsWhenOverLimit",
10140                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
10141         }
10142 
10143         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
10144         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
10145         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10146                 "testCanPostFgsWhenOverLimit - fgs over limit!",
10147                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
10148 
10149         waitForIdle();
10150 
10151         StatusBarNotification[] notifs =
10152                 mBinderService.getActiveNotifications(sbn.getPackageName());
10153         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
10154         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
10155                 mService.getNotificationRecordCount());
10156     }
10157 
10158     @Test
10159     public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
10160         when(mAmi.applyForegroundServiceNotification(
10161                 any(), anyString(), anyInt(), anyString(), anyInt()))
10162                 .thenReturn(SHOW_IMMEDIATELY);
10163         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
10164             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
10165                     i, null, false).getSbn();
10166             mBinderService.enqueueNotificationWithTag(PKG, PKG,
10167                     "testCanPostFgsWhenOverLimit",
10168                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
10169             waitForIdle();
10170         }
10171 
10172         final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
10173                 100, null, false).getSbn();
10174         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
10175         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10176                 "testCanPostFgsWhenOverLimit - fgs over limit!",
10177                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
10178 
10179         final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
10180                 101, null, false).getSbn();
10181         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10182                 "testCanPostFgsWhenOverLimit - non fgs over limit!",
10183                 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
10184 
10185 
10186         when(mAmi.applyForegroundServiceNotification(
10187                 any(), anyString(), anyInt(), anyString(), anyInt()))
10188                 .thenReturn(NOT_FOREGROUND_SERVICE);
10189         final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel,
10190                 101, null, false).getSbn();
10191         sbn3.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
10192         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10193                 "testCanPostFgsWhenOverLimit - fake fgs over limit!",
10194                 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId());
10195 
10196         waitForIdle();
10197 
10198         StatusBarNotification[] notifs =
10199                 mBinderService.getActiveNotifications(sbn.getPackageName());
10200         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
10201         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
10202                 mService.getNotificationRecordCount());
10203     }
10204 
10205     @Test
10206     public void testIsVisibleToListener_notEnabled() {
10207         StatusBarNotification sbn = mock(StatusBarNotification.class);
10208         when(sbn.getUserId()).thenReturn(10);
10209         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10210         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10211         info.userid = 10;
10212         when(info.isSameUser(anyInt())).thenReturn(true);
10213         when(assistant.isSameUser(anyInt())).thenReturn(true);
10214         when(info.enabledAndUserMatches(info.userid)).thenReturn(false);
10215         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10216 
10217         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10218     }
10219 
10220     @Test
10221     public void testIsVisibleToListener_noAssistant() {
10222         StatusBarNotification sbn = mock(StatusBarNotification.class);
10223         when(sbn.getUserId()).thenReturn(10);
10224         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10225         info.userid = 10;
10226         when(info.isSameUser(anyInt())).thenReturn(true);
10227         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10228         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(null);
10229 
10230         assertTrue(mService.isVisibleToListener(sbn, 0, info));
10231     }
10232 
10233     @Test
10234     public void testIsVisibleToListener_assistant_differentUser() {
10235         StatusBarNotification sbn = mock(StatusBarNotification.class);
10236         when(sbn.getUserId()).thenReturn(10);
10237         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10238         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10239         info.userid = 0;
10240         when(info.isSameUser(anyInt())).thenReturn(true);
10241         when(assistant.isSameUser(anyInt())).thenReturn(true);
10242         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10243         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10244 
10245         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10246     }
10247 
10248     @Test
10249     public void testIsVisibleToListener_assistant_sameUser() {
10250         StatusBarNotification sbn = mock(StatusBarNotification.class);
10251         when(sbn.getUserId()).thenReturn(10);
10252         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10253         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10254         info.userid = 10;
10255         when(info.isSameUser(anyInt())).thenReturn(true);
10256         when(assistant.isSameUser(anyInt())).thenReturn(true);
10257         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10258         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10259 
10260         assertTrue(mService.isVisibleToListener(sbn, 0, info));
10261     }
10262 
10263     @Test
10264     public void testIsVisibleToListener_mismatchedType() {
10265         when(mNlf.isTypeAllowed(anyInt())).thenReturn(false);
10266 
10267         StatusBarNotification sbn = mock(StatusBarNotification.class);
10268         when(sbn.getUserId()).thenReturn(10);
10269         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10270         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10271         info.userid = 10;
10272         when(info.isSameUser(anyInt())).thenReturn(true);
10273         when(assistant.isSameUser(anyInt())).thenReturn(true);
10274         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10275         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10276 
10277         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10278     }
10279 
10280     @Test
10281     public void testIsVisibleToListener_disallowedPackage() {
10282         when(mNlf.isPackageAllowed(any())).thenReturn(false);
10283 
10284         StatusBarNotification sbn = mock(StatusBarNotification.class);
10285         when(sbn.getUserId()).thenReturn(10);
10286         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10287         ManagedServices.ManagedServiceInfo assistant =
10288                 mock(ManagedServices.ManagedServiceInfo.class);
10289         info.userid = 10;
10290         when(info.isSameUser(anyInt())).thenReturn(true);
10291         when(assistant.isSameUser(anyInt())).thenReturn(true);
10292         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10293         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10294 
10295         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10296     }
10297 
10298     @Test
10299     public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedFirst() {
10300         final NotificationRecord parent = spy(generateNotificationRecord(
10301                 mTestNotificationChannel, 1, "group", true));
10302         final NotificationRecord child = spy(generateNotificationRecord(
10303                 mTestNotificationChannel, 2, "group", false));
10304         mService.addNotification(parent);
10305         mService.addNotification(child);
10306 
10307         InOrder inOrder = inOrder(parent, child);
10308 
10309         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
10310                 parent.getUserId());
10311         waitForIdle();
10312         inOrder.verify(parent).recordDismissalSentiment(anyInt());
10313         inOrder.verify(child).recordDismissalSentiment(anyInt());
10314     }
10315 
10316     @Test
10317     public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedSecond() {
10318         final NotificationRecord parent = spy(generateNotificationRecord(
10319                 mTestNotificationChannel, 1, "group", true));
10320         final NotificationRecord child = spy(generateNotificationRecord(
10321                 mTestNotificationChannel, 2, "group", false));
10322         mService.addNotification(child);
10323         mService.addNotification(parent);
10324 
10325         InOrder inOrder = inOrder(parent, child);
10326 
10327         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
10328                 parent.getUserId());
10329         waitForIdle();
10330         inOrder.verify(parent).recordDismissalSentiment(anyInt());
10331         inOrder.verify(child).recordDismissalSentiment(anyInt());
10332     }
10333 
10334     @Test
10335     public void testImmutableBubbleIntent() throws Exception {
10336         when(mAmi.getPendingIntentFlags(pi1))
10337                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10338         NotificationRecord r = generateMessageBubbleNotifRecord(true,
10339                 mTestNotificationChannel, 7, "testImmutableBubbleIntent", null, false);
10340         try {
10341             mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10342                     r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10343 
10344             waitForIdle();
10345             fail("Allowed a bubble with an immutable intent to be posted");
10346         } catch (IllegalArgumentException e) {
10347             // good
10348         }
10349     }
10350 
10351     @Test
10352     public void testMutableBubbleIntent() throws Exception {
10353         when(mAmi.getPendingIntentFlags(pi1))
10354                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10355         NotificationRecord r = generateMessageBubbleNotifRecord(true,
10356                 mTestNotificationChannel, 7, "testMutableBubbleIntent", null, false);
10357 
10358         mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10359                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10360 
10361         waitForIdle();
10362         StatusBarNotification[] notifs =
10363                 mBinderService.getActiveNotifications(r.getSbn().getPackageName());
10364         assertEquals(1, notifs.length);
10365     }
10366 
10367     @Test
10368     public void testImmutableDirectReplyActionIntent() throws Exception {
10369         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10370                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10371         NotificationRecord r = generateMessageBubbleNotifRecord(false,
10372                 mTestNotificationChannel, 7, "testImmutableDirectReplyActionIntent", null, false);
10373         try {
10374             mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10375                     r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10376 
10377             waitForIdle();
10378             fail("Allowed a direct reply with an immutable intent to be posted");
10379         } catch (IllegalArgumentException e) {
10380             // good
10381         }
10382     }
10383 
10384     @Test
10385     public void testMutableDirectReplyActionIntent() throws Exception {
10386         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10387                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10388         NotificationRecord r = generateMessageBubbleNotifRecord(false,
10389                 mTestNotificationChannel, 7, "testMutableDirectReplyActionIntent", null, false);
10390         mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10391                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10392 
10393         waitForIdle();
10394         StatusBarNotification[] notifs =
10395                 mBinderService.getActiveNotifications(r.getSbn().getPackageName());
10396         assertEquals(1, notifs.length);
10397     }
10398 
10399     @Test
10400     public void testImmutableDirectReplyContextualActionIntent() throws Exception {
10401         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10402                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10403         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10404 
10405         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10406         ArrayList<Notification.Action> extraAction = new ArrayList<>();
10407         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
10408         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
10409                 PendingIntent.FLAG_IMMUTABLE);
10410         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
10411         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
10412                 inputIntent).addRemoteInput(remoteInput)
10413                 .build();
10414         extraAction.add(replyAction);
10415         Bundle signals = new Bundle();
10416         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
10417         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
10418                 r.getUser());
10419         r.addAdjustment(adjustment);
10420         r.applyAdjustments();
10421 
10422         try {
10423             mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(),
10424                     r.getSbn().getTag(), r, false, false);
10425             fail("Allowed a contextual direct reply with an immutable intent to be posted");
10426         } catch (IllegalArgumentException e) {
10427             // good
10428         }
10429     }
10430 
10431     @Test
10432     public void testMutableDirectReplyContextualActionIntent() throws Exception {
10433         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10434                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10435         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10436         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10437         ArrayList<Notification.Action> extraAction = new ArrayList<>();
10438         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
10439         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
10440                 new Intent().setPackage(mContext.getPackageName()),
10441                 PendingIntent.FLAG_MUTABLE);
10442         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
10443         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
10444                 inputIntent).addRemoteInput(remoteInput)
10445                 .build();
10446         extraAction.add(replyAction);
10447         Bundle signals = new Bundle();
10448         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
10449         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
10450                 r.getUser());
10451         r.addAdjustment(adjustment);
10452         r.applyAdjustments();
10453 
10454         mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(),
10455                 r.getSbn().getTag(), r, false, false);
10456     }
10457 
10458     @Test
10459     public void testImmutableActionIntent() throws Exception {
10460         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10461                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10462         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10463 
10464         mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10465                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10466 
10467         waitForIdle();
10468         StatusBarNotification[] notifs =
10469                 mBinderService.getActiveNotifications(r.getSbn().getPackageName());
10470         assertEquals(1, notifs.length);
10471     }
10472 
10473     @Test
10474     public void testImmutableContextualActionIntent() throws Exception {
10475         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10476                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10477         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10478         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10479         ArrayList<Notification.Action> extraAction = new ArrayList<>();
10480         extraAction.add(new Notification.Action(0, "hello", null));
10481         Bundle signals = new Bundle();
10482         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
10483         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
10484                 r.getUser());
10485         r.addAdjustment(adjustment);
10486         r.applyAdjustments();
10487 
10488         mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(),
10489                     r.getSbn().getTag(), r, false, false);
10490     }
10491 
10492     @Test
10493     public void testMigrateNotificationFilter_migrationAllAllowed() throws Exception {
10494         int uid = 9000;
10495         int[] userIds = new int[] {mUserId, 1000};
10496         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10497         List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries");
10498         for (int userId : userIds) {
10499             for (String pkg : disallowedApps) {
10500                 when(mPackageManager.getPackageUid(pkg, 0, userId)).thenReturn(uid++);
10501             }
10502         }
10503 
10504         when(mListeners.getNotificationListenerFilter(any())).thenReturn(
10505                 new NotificationListenerFilter());
10506 
10507         mBinderService.migrateNotificationFilter(null,
10508                 FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
10509                 disallowedApps);
10510 
10511         ArgumentCaptor<NotificationListenerFilter> captor =
10512                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10513         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10514 
10515         assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
10516                 captor.getValue().getTypes());
10517         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9000)));
10518         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9002)));
10519         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9003)));
10520 
10521         // hypothetical other user untouched
10522         assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 10000)));
10523     }
10524 
10525     @Test
10526     public void testMigrateNotificationFilter_invalidPackage() throws Exception {
10527         int[] userIds = new int[] {mUserId, 1000};
10528         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10529         List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries");
10530         for (int userId : userIds) {
10531             when(mPackageManager.getPackageUid("apples", 0, userId)).thenThrow(
10532                     new RemoteException(""));
10533             when(mPackageManager.getPackageUid("bananas", 0, userId)).thenReturn(9000);
10534             when(mPackageManager.getPackageUid("cherries", 0, userId)).thenReturn(9001);
10535         }
10536 
10537         when(mListeners.getNotificationListenerFilter(any())).thenReturn(
10538                 new NotificationListenerFilter());
10539 
10540         mBinderService.migrateNotificationFilter(null,
10541                 FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
10542                 disallowedApps);
10543 
10544         ArgumentCaptor<NotificationListenerFilter> captor =
10545                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10546         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10547 
10548         assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
10549                 captor.getValue().getTypes());
10550         // valid values stay
10551         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("bananas", 9000)));
10552         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9001)));
10553         // don't store invalid values
10554         for (VersionedPackage vp : captor.getValue().getDisallowedPackages()) {
10555             assertNotEquals("apples", vp.getPackageName());
10556         }
10557     }
10558 
10559     @Test
10560     public void testMigrateNotificationFilter_noPreexistingFilter() throws Exception {
10561         int[] userIds = new int[] {mUserId};
10562         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10563         List<String> disallowedApps = ImmutableList.of("apples");
10564         when(mPackageManager.getPackageUid("apples", 0, mUserId))
10565                 .thenReturn(1001);
10566 
10567         when(mListeners.getNotificationListenerFilter(any())).thenReturn(null);
10568 
10569         mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING,
10570                 disallowedApps);
10571 
10572         ArgumentCaptor<NotificationListenerFilter> captor =
10573                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10574         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10575 
10576         assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes());
10577         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
10578     }
10579 
10580     @Test
10581     public void testMigrateNotificationFilter_existingTypeFilter() throws Exception {
10582         int[] userIds = new int[] {mUserId};
10583         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10584         List<String> disallowedApps = ImmutableList.of("apples");
10585         when(mPackageManager.getPackageUid("apples", 0, mUserId))
10586                 .thenReturn(1001);
10587 
10588         when(mListeners.getNotificationListenerFilter(any())).thenReturn(
10589                 new NotificationListenerFilter(FLAG_FILTER_TYPE_CONVERSATIONS, new ArraySet<>()));
10590 
10591         mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING,
10592                 disallowedApps);
10593 
10594         ArgumentCaptor<NotificationListenerFilter> captor =
10595                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10596         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10597 
10598         // type isn't saved but pkg list is
10599         assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS, captor.getValue().getTypes());
10600         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
10601     }
10602 
10603     @Test
10604     public void testMigrateNotificationFilter_existingPkgFilter() throws Exception {
10605         int[] userIds = new int[] {mUserId};
10606         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10607         List<String> disallowedApps = ImmutableList.of("apples");
10608         when(mPackageManager.getPackageUid("apples", 0, mUserId))
10609                 .thenReturn(1001);
10610 
10611         NotificationListenerFilter preexisting = new NotificationListenerFilter();
10612         preexisting.addPackage(new VersionedPackage("test", 1002));
10613         when(mListeners.getNotificationListenerFilter(any())).thenReturn(preexisting);
10614 
10615         mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING,
10616                 disallowedApps);
10617 
10618         ArgumentCaptor<NotificationListenerFilter> captor =
10619                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10620         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10621 
10622         // type is saved but pkg list isn't
10623         assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes());
10624         assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
10625         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002)));
10626     }
10627 
10628     @Test
10629     public void testGetNotificationChannelsBypassingDnd_blocked() throws RemoteException {
10630         mService.setPreferencesHelper(mPreferencesHelper);
10631 
10632         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10633 
10634         assertThat(mBinderService.getNotificationChannelsBypassingDnd(PKG, mUid).getList())
10635                 .isEmpty();
10636         verify(mPreferencesHelper, never()).getNotificationChannelsBypassingDnd(PKG, mUid);
10637     }
10638 
10639     @Test
10640     public void testMatchesCallFilter_noPermissionShouldThrow() throws Exception {
10641         // set the testable NMS to not system uid/appid
10642         mService.isSystemUid = false;
10643         mService.isSystemAppId = false;
10644 
10645         // make sure a caller without listener access or read_contacts permission can't call
10646         // matchesCallFilter.
10647         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false);
10648         doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
10649                 eq("android.permission.READ_CONTACTS"), anyString());
10650 
10651         try {
10652             // shouldn't matter what we're passing in, if we get past this line fail immediately
10653             ((INotificationManager) mService.mService).matchesCallFilter(null);
10654             fail("call to matchesCallFilter with no permissions should fail");
10655         } catch (SecurityException e) {
10656             // pass
10657         }
10658     }
10659 
10660     @Test
10661     public void testMatchesCallFilter_hasSystemPermission() throws Exception {
10662         // set the testable NMS to system uid
10663         mService.isSystemUid = true;
10664 
10665         // make sure caller doesn't have listener access or read_contacts permission
10666         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false);
10667         doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
10668                 eq("android.permission.READ_CONTACTS"), anyString());
10669 
10670         try {
10671             ((INotificationManager) mService.mService).matchesCallFilter(null);
10672             // pass, but check that we actually checked for system permissions
10673             assertTrue(mService.countSystemChecks > 0);
10674         } catch (SecurityException e) {
10675             fail("call to matchesCallFilter with just system permissions should work");
10676         }
10677     }
10678 
10679     @Test
10680     public void testMatchesCallFilter_hasListenerPermission() throws Exception {
10681         mService.isSystemUid = false;
10682         mService.isSystemAppId = false;
10683 
10684         // make sure a caller with only listener access and not read_contacts permission can call
10685         // matchesCallFilter.
10686         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(true);
10687         doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
10688                 eq("android.permission.READ_CONTACTS"), anyString());
10689 
10690         try {
10691             ((INotificationManager) mService.mService).matchesCallFilter(null);
10692             // pass, this is not a functionality test
10693         } catch (SecurityException e) {
10694             fail("call to matchesCallFilter with listener permissions should work");
10695         }
10696     }
10697 
10698     @Test
10699     public void testMatchesCallFilter_hasContactsPermission() throws Exception {
10700         mService.isSystemUid = false;
10701         mService.isSystemAppId = false;
10702 
10703         // make sure a caller with only read_contacts permission and not listener access can call
10704         // matchesCallFilter.
10705         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false);
10706         doNothing().when(mContext).enforceCallingPermission(
10707                 eq("android.permission.READ_CONTACTS"), anyString());
10708 
10709         try {
10710             ((INotificationManager) mService.mService).matchesCallFilter(null);
10711             // pass, this is not a functionality test
10712         } catch (SecurityException e) {
10713             fail("call to matchesCallFilter with listener permissions should work");
10714         }
10715     }
10716 
10717     @Test
10718     public void testMediaNotificationsBypassBlock() throws Exception {
10719         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10720                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10721         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10722 
10723         Notification.Builder nb = new Notification.Builder(
10724                 mContext, mTestNotificationChannel.getId())
10725                 .setContentTitle("foo")
10726                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10727                 .addAction(new Notification.Action.Builder(null, "test", null).build());
10728         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10729                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10730         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10731 
10732         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10733 
10734         // normal blocked notifications - blocked
10735         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10736                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10737 
10738         // just using the style - blocked
10739         nb.setStyle(new Notification.MediaStyle());
10740         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10741                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10742         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10743 
10744         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10745                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10746 
10747         // using the style, but incorrect type in session - blocked
10748         nb.setStyle(new Notification.MediaStyle());
10749         Bundle extras = new Bundle();
10750         extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent());
10751         nb.addExtras(extras);
10752         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10753                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10754         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10755 
10756         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10757                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10758 
10759         // style + media session - bypasses block
10760         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
10761         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10762                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10763         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10764 
10765         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10766                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
10767     }
10768 
10769     @Test
10770     public void testMediaNotificationsBypassBlock_atPost() throws Exception {
10771         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
10772         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10773 
10774         Notification.Builder nb = new Notification.Builder(
10775                 mContext, mTestNotificationChannel.getId())
10776                 .setContentTitle("foo")
10777                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10778                 .addAction(new Notification.Action.Builder(null, "test", null).build());
10779         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10780                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10781         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10782 
10783         when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false);
10784 
10785         mService.addEnqueuedNotification(r);
10786         NotificationManagerService.PostNotificationRunnable runnable =
10787                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
10788                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
10789         runnable.run();
10790         waitForIdle();
10791 
10792         verify(mUsageStats).registerBlocked(any());
10793         verify(mUsageStats, never()).registerPostedByApp(any());
10794 
10795         // just using the style - blocked
10796         mService.clearNotifications();
10797         reset(mUsageStats);
10798         nb.setStyle(new Notification.MediaStyle());
10799         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10800                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10801         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10802 
10803         mService.addEnqueuedNotification(r);
10804         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
10805                 r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
10806         runnable.run();
10807         waitForIdle();
10808 
10809         verify(mUsageStats).registerBlocked(any());
10810         verify(mUsageStats, never()).registerPostedByApp(any());
10811 
10812         // style + media session - bypasses block
10813         mService.clearNotifications();
10814         reset(mUsageStats);
10815         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
10816         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10817                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10818         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10819 
10820         mService.addEnqueuedNotification(r);
10821         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
10822                 r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
10823         runnable.run();
10824         waitForIdle();
10825 
10826         verify(mUsageStats, never()).registerBlocked(any());
10827         verify(mUsageStats).registerPostedByApp(any());
10828     }
10829 
10830     @Test
10831     public void testCallNotificationsBypassBlock() throws Exception {
10832         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10833                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10834         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10835 
10836         Notification.Builder nb = new Notification.Builder(
10837                 mContext, mTestNotificationChannel.getId())
10838                 .setContentTitle("foo")
10839                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10840                 .addAction(new Notification.Action.Builder(null, "test", null).build());
10841         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10842                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10843         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10844 
10845         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10846 
10847         // normal blocked notifications - blocked
10848         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10849                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10850 
10851         // just using the style - blocked
10852         Person person = new Person.Builder()
10853                 .setName("caller")
10854                 .build();
10855         nb.setStyle(Notification.CallStyle.forOngoingCall(
10856                 person, mock(PendingIntent.class)));
10857         nb.setFullScreenIntent(mock(PendingIntent.class), true);
10858         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10859                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10860         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10861 
10862         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10863                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10864 
10865         // style + managed call - bypasses block
10866         when(mTelecomManager.isInManagedCall()).thenReturn(true);
10867         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10868                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
10869 
10870         // style + self managed call - bypasses block
10871         when(mTelecomManager.isInSelfManagedCall(
10872                 r.getSbn().getPackageName(), r.getUser())).thenReturn(true);
10873         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10874                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
10875 
10876         // set telecom manager to null - blocked
10877         mService.setTelecomManager(null);
10878         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10879                            r.getSbn().getId(), r.getSbn().getTag(), r, false, false))
10880                 .isFalse();
10881 
10882         // set telecom feature to false - blocked
10883         when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false);
10884         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10885                            r.getSbn().getId(), r.getSbn().getTag(), r, false, false))
10886                 .isFalse();
10887 
10888         // telecom manager is not ready - blocked
10889         mService.setTelecomManager(mTelecomManager);
10890         when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready"));
10891         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10892                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false))
10893                 .isFalse();
10894     }
10895 
10896     @Test
10897     public void testCallNotificationsBypassBlock_atPost() throws Exception {
10898         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
10899         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10900 
10901         Notification.Builder nb =
10902                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
10903                         .setContentTitle("foo")
10904                         .setSmallIcon(android.R.drawable.sym_def_app_icon)
10905                         .addAction(new Notification.Action.Builder(null, "test", null).build());
10906         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10907                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10908         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10909 
10910         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10911 
10912         // normal blocked notifications - blocked
10913         mService.addEnqueuedNotification(r);
10914         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10915                 mPostNotificationTrackerFactory.newTracker(null)).run();
10916         waitForIdle();
10917 
10918         verify(mUsageStats).registerBlocked(any());
10919         verify(mUsageStats, never()).registerPostedByApp(any());
10920 
10921         // just using the style - blocked
10922         mService.clearNotifications();
10923         reset(mUsageStats);
10924         Person person = new Person.Builder().setName("caller").build();
10925         nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class)));
10926         nb.setFullScreenIntent(mock(PendingIntent.class), true);
10927         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(),
10928                 UserHandle.getUserHandleForUid(mUid), null, 0);
10929         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10930 
10931         mService.addEnqueuedNotification(r);
10932         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10933                 mPostNotificationTrackerFactory.newTracker(null)).run();
10934         waitForIdle();
10935 
10936         verify(mUsageStats).registerBlocked(any());
10937         verify(mUsageStats, never()).registerPostedByApp(any());
10938 
10939         // style + managed call - bypasses block
10940         mService.clearNotifications();
10941         reset(mUsageStats);
10942         when(mTelecomManager.isInManagedCall()).thenReturn(true);
10943 
10944         mService.addEnqueuedNotification(r);
10945         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10946                 mPostNotificationTrackerFactory.newTracker(null)).run();
10947         waitForIdle();
10948 
10949         verify(mUsageStats, never()).registerBlocked(any());
10950         verify(mUsageStats).registerPostedByApp(any());
10951 
10952         // style + self managed call - bypasses block
10953         mService.clearNotifications();
10954         reset(mUsageStats);
10955         when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser()))
10956                 .thenReturn(true);
10957 
10958         mService.addEnqueuedNotification(r);
10959         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10960                 mPostNotificationTrackerFactory.newTracker(null)).run();
10961         waitForIdle();
10962 
10963         verify(mUsageStats, never()).registerBlocked(any());
10964         verify(mUsageStats).registerPostedByApp(any());
10965 
10966         // set telecom manager to null - notifications should be blocked
10967         // but post notifications runnable should not crash
10968         mService.clearNotifications();
10969         reset(mUsageStats);
10970         mService.setTelecomManager(null);
10971 
10972         mService.addEnqueuedNotification(r);
10973         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10974                 mPostNotificationTrackerFactory.newTracker(null)).run();
10975         waitForIdle();
10976 
10977         verify(mUsageStats).registerBlocked(any());
10978         verify(mUsageStats, never()).registerPostedByApp(any());
10979 
10980         // set FEATURE_TELECOM to false - notifications should be blocked
10981         // but post notifications runnable should not crash
10982         mService.setTelecomManager(mTelecomManager);
10983         when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false);
10984         reset(mUsageStats);
10985         mService.setTelecomManager(null);
10986 
10987         mService.addEnqueuedNotification(r);
10988         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10989                 mPostNotificationTrackerFactory.newTracker(null)).run();
10990         waitForIdle();
10991 
10992         verify(mUsageStats).registerBlocked(any());
10993         verify(mUsageStats, never()).registerPostedByApp(any());
10994 
10995         // telecom is not ready - notifications should be blocked but no crashes
10996         mService.setTelecomManager(mTelecomManager);
10997         when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready"));
10998         reset(mUsageStats);
10999 
11000         mService.addEnqueuedNotification(r);
11001         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
11002                 mPostNotificationTrackerFactory.newTracker(null)).run();
11003         waitForIdle();
11004 
11005         verify(mUsageStats).registerBlocked(any());
11006         verify(mUsageStats, never()).registerPostedByApp(any());
11007     }
11008 
11009     @Test
11010     public void testGetAllUsersNotificationPermissions() {
11011         // In this case, there are multiple users each with notification permissions (and also,
11012         // for good measure, some without).
11013         // make sure the collection returned contains info for all of them
11014         final List<UserInfo> userInfos = new ArrayList<>();
11015         userInfos.add(new UserInfo(0, "user0", 0));
11016         userInfos.add(new UserInfo(1, "user1", 0));
11017         userInfos.add(new UserInfo(2, "user2", 0));
11018         when(mUm.getUsers()).thenReturn(userInfos);
11019 
11020         // construct the permissions for each of them
11021         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> permissions0 = new ArrayMap<>(),
11022                 permissions1 = new ArrayMap<>();
11023         permissions0.put(new Pair<>(10, "package1"), new Pair<>(true, false));
11024         permissions0.put(new Pair<>(20, "package2"), new Pair<>(false, true));
11025         permissions1.put(new Pair<>(11, "package1"), new Pair<>(false, false));
11026         permissions1.put(new Pair<>(21, "package2"), new Pair<>(true, true));
11027         when(mPermissionHelper.getNotificationPermissionValues(0)).thenReturn(permissions0);
11028         when(mPermissionHelper.getNotificationPermissionValues(1)).thenReturn(permissions1);
11029         when(mPermissionHelper.getNotificationPermissionValues(2)).thenReturn(new ArrayMap<>());
11030 
11031         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> combinedPermissions =
11032                 mService.getAllUsersNotificationPermissions();
11033         assertTrue(combinedPermissions.get(new Pair<>(10, "package1")).first);
11034         assertFalse(combinedPermissions.get(new Pair<>(10, "package1")).second);
11035         assertFalse(combinedPermissions.get(new Pair<>(20, "package2")).first);
11036         assertTrue(combinedPermissions.get(new Pair<>(20, "package2")).second);
11037         assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).first);
11038         assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).second);
11039         assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).first);
11040         assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).second);
11041     }
11042 
11043     @Test
11044     public void testGetActiveNotification_filtersUsers() throws Exception {
11045         when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
11046 
11047         NotificationRecord nr0 =
11048                 generateNotificationRecord(mTestNotificationChannel, 0);
11049         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
11050                 nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId());
11051 
11052         NotificationRecord nr10 =
11053                 generateNotificationRecord(mTestNotificationChannel, 10);
11054         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
11055                 nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId());
11056 
11057         NotificationRecord nr11 =
11058                 generateNotificationRecord(mTestNotificationChannel, 11);
11059         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
11060                 nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId());
11061         waitForIdle();
11062 
11063         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
11064         assertEquals(2, notifs.length);
11065         for (StatusBarNotification sbn : notifs) {
11066             if (sbn.getUserId() == 11) {
11067                 fail("leaked data across users");
11068             }
11069         }
11070     }
11071 
11072     @Test
11073     public void testUngroupingOngoingAutoSummary() throws Exception {
11074         NotificationRecord nr0 =
11075                 generateNotificationRecord(mTestNotificationChannel, 0);
11076         NotificationRecord nr1 =
11077                 generateNotificationRecord(mTestNotificationChannel, 0);
11078         nr1.getSbn().getNotification().flags |= FLAG_ONGOING_EVENT;
11079 
11080         mService.addNotification(nr0);
11081         mService.addNotification(nr1);
11082 
11083         // grouphelper is a mock here, so make the calls it would make
11084 
11085         // add summary
11086         mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(),
11087                 nr1.getSbn().getPackageName(), nr1.getKey(),
11088                 GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT));
11089 
11090         // cancel both children
11091         mBinderService.cancelNotificationWithTag(PKG, PKG, nr0.getSbn().getTag(),
11092                 nr0.getSbn().getId(), nr0.getSbn().getUserId());
11093         mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.getSbn().getTag(),
11094                 nr1.getSbn().getId(), nr1.getSbn().getUserId());
11095         waitForIdle();
11096 
11097         // group helper would send 'remove summary' event
11098         mService.clearAutogroupSummaryLocked(nr1.getUserId(), nr1.getSbn().getPackageName());
11099         waitForIdle();
11100 
11101         // make sure the summary was removed and not re-posted
11102         assertThat(mService.getNotificationRecordCount()).isEqualTo(0);
11103     }
11104 
11105     @Test
11106     public void testUngroupingAutoSummary_differentUsers() throws Exception {
11107         NotificationRecord nr0 =
11108                 generateNotificationRecord(mTestNotificationChannel, 0, USER_SYSTEM);
11109         NotificationRecord nr1 =
11110                 generateNotificationRecord(mTestNotificationChannel, 1, USER_SYSTEM);
11111 
11112         // add notifications + summary for USER_SYSTEM
11113         mService.addNotification(nr0);
11114         mService.addNotification(nr1);
11115         mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(),
11116                 nr1.getSbn().getPackageName(), nr1.getKey(), GroupHelper.BASE_FLAGS));
11117 
11118         // add notifications + summary for USER_ALL
11119         NotificationRecord nr0_all =
11120                 generateNotificationRecord(mTestNotificationChannel, 2, UserHandle.USER_ALL);
11121         NotificationRecord nr1_all =
11122                 generateNotificationRecord(mTestNotificationChannel, 3, UserHandle.USER_ALL);
11123 
11124         mService.addNotification(nr0_all);
11125         mService.addNotification(nr1_all);
11126         mService.addNotification(mService.createAutoGroupSummary(nr0_all.getUserId(),
11127                 nr0_all.getSbn().getPackageName(), nr0_all.getKey(), GroupHelper.BASE_FLAGS));
11128 
11129         // cancel both children for USER_ALL
11130         mBinderService.cancelNotificationWithTag(PKG, PKG, nr0_all.getSbn().getTag(),
11131                 nr0_all.getSbn().getId(), UserHandle.USER_ALL);
11132         mBinderService.cancelNotificationWithTag(PKG, PKG, nr1_all.getSbn().getTag(),
11133                 nr1_all.getSbn().getId(), UserHandle.USER_ALL);
11134         waitForIdle();
11135 
11136         // group helper would send 'remove summary' event
11137         mService.clearAutogroupSummaryLocked(UserHandle.USER_ALL,
11138                 nr0_all.getSbn().getPackageName());
11139         waitForIdle();
11140 
11141         // make sure the right summary was removed
11142         assertThat(mService.getNotificationCount(nr0_all.getSbn().getPackageName(),
11143                 UserHandle.USER_ALL, 0, null)).isEqualTo(0);
11144 
11145         // the USER_SYSTEM notifications + summary were not removed
11146         assertThat(mService.getNotificationCount(nr0.getSbn().getPackageName(),
11147                 USER_SYSTEM, 0, null)).isEqualTo(3);
11148     }
11149 
11150     @Test
11151     public void testStrongAuthTracker_isInLockDownMode() {
11152         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
11153                 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
11154         mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
11155         assertTrue(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
11156         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(mContext.getUserId());
11157         mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
11158         assertFalse(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
11159     }
11160 
11161     @Test
11162     public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() {
11163         // post 2 notifications from 2 packages
11164         NotificationRecord pkgA = new NotificationRecord(mContext,
11165                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
11166         mService.addNotification(pkgA);
11167         NotificationRecord pkgB = new NotificationRecord(mContext,
11168                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
11169         mService.addNotification(pkgB);
11170 
11171         // when entering the lockdown mode, cancel the 2 notifications.
11172         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
11173                 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
11174         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11175         assertTrue(mStrongAuthTracker.isInLockDownMode(0));
11176 
11177         // the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN.
11178         ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
11179         verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any());
11180         assertEquals(REASON_LOCKDOWN, captor.getValue().intValue());
11181 
11182         // exit lockdown mode.
11183         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
11184         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11185         assertFalse(mStrongAuthTracker.isInLockDownMode(0));
11186 
11187         // the notifyPostedLocked function is called twice.
11188         verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong());
11189         //verify(mListeners, times(2)).notifyPostedLocked(any(), any());
11190     }
11191 
11192     @Test
11193     public void testMakeRankingUpdateLockedInLockDownMode() {
11194         // post 2 notifications from a same package
11195         NotificationRecord pkgA = new NotificationRecord(mContext,
11196                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
11197         mService.addNotification(pkgA);
11198         NotificationRecord pkgB = new NotificationRecord(mContext,
11199                 generateSbn("a", 1000, 9, 1), mTestNotificationChannel);
11200         mService.addNotification(pkgB);
11201 
11202         mService.setIsVisibleToListenerReturnValue(true);
11203         NotificationRankingUpdate nru = mService.makeRankingUpdateLocked(null);
11204         assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
11205 
11206         // when only user 0 entering the lockdown mode, its notification will be suppressed.
11207         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
11208                 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
11209         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11210         assertTrue(mStrongAuthTracker.isInLockDownMode(0));
11211         assertFalse(mStrongAuthTracker.isInLockDownMode(1));
11212 
11213         nru = mService.makeRankingUpdateLocked(null);
11214         assertEquals(1, nru.getRankingMap().getOrderedKeys().length);
11215 
11216         // User 0 exits lockdown mode. Its notification will be resumed.
11217         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
11218         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11219         assertFalse(mStrongAuthTracker.isInLockDownMode(0));
11220         assertFalse(mStrongAuthTracker.isInLockDownMode(1));
11221 
11222         nru = mService.makeRankingUpdateLocked(null);
11223         assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
11224     }
11225 
11226     @Test
11227     public void testMaybeShowReviewPermissionsNotification_flagOff() {
11228         mService.setShowReviewPermissionsNotification(false);
11229         reset(mMockNm);
11230 
11231         // If state is SHOULD_SHOW, it would show, but not if the flag is off!
11232         Settings.Global.putInt(mContext.getContentResolver(),
11233                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11234                 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
11235         mService.maybeShowInitialReviewPermissionsNotification();
11236         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11237     }
11238 
11239     @Test
11240     public void testMaybeShowReviewPermissionsNotification_unknown() {
11241         mService.setShowReviewPermissionsNotification(true);
11242         reset(mMockNm);
11243 
11244         // Set up various possible states of the settings int and confirm whether or not the
11245         // notification is shown as expected
11246 
11247         // Initial state: default/unknown setting, make sure nothing happens
11248         Settings.Global.putInt(mContext.getContentResolver(),
11249                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11250                 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN);
11251         mService.maybeShowInitialReviewPermissionsNotification();
11252         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11253     }
11254 
11255     @Test
11256     public void testMaybeShowReviewPermissionsNotification_shouldShow() {
11257         mService.setShowReviewPermissionsNotification(true);
11258         reset(mMockNm);
11259 
11260         // If state is SHOULD_SHOW, it ... should show
11261         Settings.Global.putInt(mContext.getContentResolver(),
11262                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11263                 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
11264         mService.maybeShowInitialReviewPermissionsNotification();
11265         verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
11266                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
11267                 any(Notification.class));
11268     }
11269 
11270     @Test
11271     public void testMaybeShowReviewPermissionsNotification_alreadyShown() {
11272         mService.setShowReviewPermissionsNotification(true);
11273         reset(mMockNm);
11274 
11275         // If state is either USER_INTERACTED or DISMISSED, we should not show this on boot
11276         Settings.Global.putInt(mContext.getContentResolver(),
11277                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11278                 NotificationManagerService.REVIEW_NOTIF_STATE_USER_INTERACTED);
11279         mService.maybeShowInitialReviewPermissionsNotification();
11280 
11281         Settings.Global.putInt(mContext.getContentResolver(),
11282                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11283                 NotificationManagerService.REVIEW_NOTIF_STATE_DISMISSED);
11284         mService.maybeShowInitialReviewPermissionsNotification();
11285 
11286         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11287     }
11288 
11289     @Test
11290     public void testMaybeShowReviewPermissionsNotification_reshown() {
11291         mService.setShowReviewPermissionsNotification(true);
11292         reset(mMockNm);
11293 
11294         // If we have re-shown the notification and the user did not subsequently interacted with
11295         // it, then make sure we show when trying on boot
11296         Settings.Global.putInt(mContext.getContentResolver(),
11297                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11298                 NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN);
11299         mService.maybeShowInitialReviewPermissionsNotification();
11300         verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
11301                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
11302                 any(Notification.class));
11303     }
11304 
11305     @Test
11306     public void testRescheduledReviewPermissionsNotification() {
11307         mService.setShowReviewPermissionsNotification(true);
11308         reset(mMockNm);
11309 
11310         // when rescheduled, the notification goes through the NotificationManagerInternal service
11311         // this call doesn't need to know anything about previously scheduled state -- if called,
11312         // it should send the notification & write the appropriate int to Settings
11313         mInternalService.sendReviewPermissionsNotification();
11314 
11315         // Notification should be sent
11316         verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
11317                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
11318                 any(Notification.class));
11319 
11320         // write STATE_RESHOWN to settings
11321         assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN,
11322                 Settings.Global.getInt(mContext.getContentResolver(),
11323                         Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11324                         NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN));
11325     }
11326 
11327     @Test
11328     public void testRescheduledReviewPermissionsNotification_flagOff() {
11329         mService.setShowReviewPermissionsNotification(false);
11330         reset(mMockNm);
11331 
11332         // no notification should be sent if the flag is off
11333         mInternalService.sendReviewPermissionsNotification();
11334         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11335     }
11336 
11337     private void verifyStickyHun(Flag flag, int permissionState, boolean appRequested,
11338             boolean isSticky) throws Exception {
11339 
11340         when(mPermissionHelper.hasRequestedPermission(Manifest.permission.USE_FULL_SCREEN_INTENT,
11341                 PKG, mUserId)).thenReturn(appRequested);
11342 
11343         mTestFlagResolver.setFlagOverride(flag, true);
11344 
11345         when(mPermissionManager.checkPermissionForDataDelivery(
11346                 eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any()))
11347                 .thenReturn(permissionState);
11348 
11349         Notification n = new Notification.Builder(mContext, "test")
11350                 .setFullScreenIntent(mock(PendingIntent.class), true)
11351                 .build();
11352 
11353         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11354 
11355         final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
11356 
11357         if (isSticky) {
11358             assertNotSame(0, stickyFlag);
11359         } else {
11360             assertSame(0, stickyFlag);
11361         }
11362     }
11363 
11364     @Test
11365     public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun()
11366             throws Exception {
11367 
11368         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11369                 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true,
11370                 /* isSticky= */ true);
11371     }
11372 
11373     @Test
11374     public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun()
11375             throws Exception {
11376 
11377         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11378                 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true,
11379                 /* isSticky= */ true);
11380     }
11381 
11382     @Test
11383     public void testFixNotification_fsiPermissionSoftDenied_appNotRequest_noShowStickyHun()
11384             throws Exception {
11385         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11386                 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, false,
11387                 /* isSticky= */ false);
11388     }
11389 
11390 
11391     @Test
11392     public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi()
11393             throws Exception {
11394 
11395         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11396                 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true,
11397                 /* isSticky= */ false);
11398     }
11399 
11400     @Test
11401     public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun()
11402             throws Exception {
11403 
11404         verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
11405                 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true,
11406                 /* isSticky= */ true);
11407     }
11408 
11409     @Test
11410     public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun()
11411             throws Exception {
11412 
11413         verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
11414                 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true,
11415                 /* isSticky= */ true);
11416     }
11417 
11418     @Test
11419     public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun()
11420             throws Exception {
11421 
11422         verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
11423                 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true,
11424                 /* isSticky= */ true);
11425     }
11426 
11427     @Test
11428     public void fixNotification_withFgsFlag_butIsNotFgs() throws Exception {
11429         final ApplicationInfo applicationInfo = new ApplicationInfo();
11430         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11431                 .thenReturn(applicationInfo);
11432 
11433         Notification n = new Notification.Builder(mContext, "test")
11434                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
11435                 .setFlag(FLAG_CAN_COLORIZE, true)
11436                 .build();
11437 
11438         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11439 
11440         assertFalse(n.isForegroundService());
11441         assertFalse(n.hasColorizedPermission());
11442     }
11443 
11444     @Test
11445     public void checkCallStyleNotification_withoutAnyValidUseCase_throws() throws Exception {
11446         Person person = new Person.Builder().setName("caller").build();
11447         Notification n = new Notification.Builder(mContext, "test")
11448                 .setStyle(Notification.CallStyle.forOngoingCall(
11449                         person, mock(PendingIntent.class)))
11450                 .build();
11451         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11452                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11453         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11454 
11455         try {
11456             mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11457                     r.getSbn().getId(), r.getSbn().getTag(), r, false, false);
11458             assertFalse("CallStyle should not be allowed without a valid use case", true);
11459         } catch (IllegalArgumentException error) {
11460             assertThat(error.getMessage()).contains("CallStyle");
11461         }
11462     }
11463 
11464     @Test
11465     public void checkCallStyleNotification_allowedForFgs() throws Exception {
11466         Person person = new Person.Builder().setName("caller").build();
11467         Notification n = new Notification.Builder(mContext, "test")
11468                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
11469                 .setStyle(Notification.CallStyle.forOngoingCall(
11470                         person, mock(PendingIntent.class)))
11471                 .build();
11472         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11473                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11474         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11475 
11476         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11477                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11478     }
11479 
11480     @Test
11481     public void checkCallStyleNotification_allowedForByForegroundService() throws Exception {
11482         Person person = new Person.Builder().setName("caller").build();
11483         Notification n = new Notification.Builder(mContext, "test")
11484                 // Without FLAG_FOREGROUND_SERVICE.
11485                 //.setFlag(FLAG_FOREGROUND_SERVICE, true)
11486                 .setStyle(Notification.CallStyle.forOngoingCall(
11487                         person, mock(PendingIntent.class)))
11488                 .build();
11489         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11490                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11491         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11492 
11493         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11494                 r.getSbn().getId(), r.getSbn().getTag(), r, false,
11495                 true /* byForegroundService */)).isTrue();
11496     }
11497 
11498     @Test
11499     public void checkCallStyleNotification_allowedForUij() throws Exception {
11500         Person person = new Person.Builder().setName("caller").build();
11501         Notification n = new Notification.Builder(mContext, "test")
11502                 .setFlag(FLAG_USER_INITIATED_JOB, true)
11503                 .setStyle(Notification.CallStyle.forOngoingCall(
11504                         person, mock(PendingIntent.class)))
11505                 .build();
11506         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11507                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11508         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11509 
11510         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11511                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11512     }
11513 
11514     @Test
11515     public void checkCallStyleNotification_allowedForFsiAllowed() throws Exception {
11516         Person person = new Person.Builder().setName("caller").build();
11517         Notification n = new Notification.Builder(mContext, "test")
11518                 .setFullScreenIntent(mock(PendingIntent.class), true)
11519                 .setStyle(Notification.CallStyle.forOngoingCall(
11520                         person, mock(PendingIntent.class)))
11521                 .build();
11522         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11523                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11524         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11525 
11526         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11527                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11528     }
11529 
11530     @Test
11531     public void checkCallStyleNotification_allowedForFsiDenied() throws Exception {
11532         Person person = new Person.Builder().setName("caller").build();
11533         Notification n = new Notification.Builder(mContext, "test")
11534                 .setFlag(Notification.FLAG_FSI_REQUESTED_BUT_DENIED, true)
11535                 .setStyle(Notification.CallStyle.forOngoingCall(
11536                         person, mock(PendingIntent.class)))
11537                 .build();
11538         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11539                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11540         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11541 
11542         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11543                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11544     }
11545 
11546     @Test
11547     public void fixSystemNotification_withOnGoingFlag_shouldBeDismissible()
11548             throws Exception {
11549         final ApplicationInfo ai = new ApplicationInfo();
11550         ai.packageName = "pkg";
11551         ai.uid = mUid;
11552         ai.flags |= ApplicationInfo.FLAG_SYSTEM;
11553 
11554         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11555                 .thenReturn(ai);
11556         when(mAppOpsManager.checkOpNoThrow(
11557                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
11558                 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED);
11559         // Given: a notification from an app on the system partition has the flag
11560         // FLAG_ONGOING_EVENT set
11561         Notification n = new Notification.Builder(mContext, "test")
11562                 .setOngoing(true)
11563                 .build();
11564 
11565         // When: fix the notification with NotificationManagerService
11566         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11567 
11568         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11569         assertSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11570     }
11571 
11572     @Test
11573     public void fixMediaNotification_withOnGoingFlag_shouldBeNonDismissible()
11574             throws Exception {
11575         // Given: a media notification has the flag FLAG_ONGOING_EVENT set
11576         Notification n = new Notification.Builder(mContext, "test")
11577                 .setOngoing(true)
11578                 .setStyle(new Notification.MediaStyle()
11579                         .setMediaSession(mock(MediaSession.Token.class)))
11580                 .build();
11581 
11582         // When: fix the notification with NotificationManagerService
11583         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11584 
11585         // Then: the notification's flag FLAG_NO_DISMISS should be set
11586         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11587     }
11588 
11589     @Test
11590     public void fixSystemNotification_defaultSearchSelectior_withOnGoingFlag_nondismissible()
11591             throws Exception {
11592         final ApplicationInfo ai = new ApplicationInfo();
11593         ai.packageName = SEARCH_SELECTOR_PKG;
11594         ai.uid = mUid;
11595         ai.flags |= ApplicationInfo.FLAG_SYSTEM;
11596 
11597         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11598                 .thenReturn(ai);
11599         when(mAppOpsManager.checkOpNoThrow(
11600                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
11601                 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED);
11602         // Given: a notification from an app on the system partition has the flag
11603         // FLAG_ONGOING_EVENT set
11604         Notification n = new Notification.Builder(mContext, "test")
11605                 .setOngoing(true)
11606                 .build();
11607 
11608         // When: fix the notification with NotificationManagerService
11609         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11610 
11611         // Then: the notification's flag FLAG_NO_DISMISS should be set
11612         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11613     }
11614 
11615     @Test
11616     public void fixCallNotification_withOnGoingFlag_shouldNotBeNonDismissible()
11617             throws Exception {
11618         // Given: a call notification has the flag FLAG_ONGOING_EVENT set
11619         Person person = new Person.Builder()
11620                 .setName("caller")
11621                 .build();
11622         Notification n = new Notification.Builder(mContext, "test")
11623                 .setOngoing(true)
11624                 .setStyle(Notification.CallStyle.forOngoingCall(
11625                         person, mock(PendingIntent.class)))
11626                 .build();
11627 
11628         // When: fix the notification with NotificationManagerService
11629         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11630 
11631         // Then: the notification's flag FLAG_NO_DISMISS should be set
11632         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11633     }
11634 
11635 
11636     @Test
11637     public void fixNonExemptNotification_withOnGoingFlag_shouldBeDismissible() throws Exception {
11638         // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
11639         Notification n = new Notification.Builder(mContext, "test")
11640                 .setOngoing(true)
11641                 .build();
11642 
11643         // When: fix the notification with NotificationManagerService
11644         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11645 
11646         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11647         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11648     }
11649 
11650     @Test
11651     public void fixNonExemptNotification_withNoDismissFlag_shouldBeDismissible()
11652             throws Exception {
11653         // Given: a non-exempt notification has the flag FLAG_NO_DISMISS set (even though this is
11654         // not allowed)
11655         Notification n = new Notification.Builder(mContext, "test")
11656                 .build();
11657         n.flags |= Notification.FLAG_NO_DISMISS;
11658 
11659         // When: fix the notification with NotificationManagerService
11660         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11661 
11662         // Then: the notification's flag FLAG_NO_DISMISS should be cleared
11663         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11664     }
11665 
11666     @Test
11667     public void fixMediaNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
11668         // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set
11669         Notification n = new Notification.Builder(mContext, "test")
11670                 .setOngoing(false)
11671                 .setStyle(new Notification.MediaStyle()
11672                         .setMediaSession(mock(MediaSession.Token.class)))
11673                 .build();
11674 
11675         // When: fix the notification with NotificationManagerService
11676         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11677 
11678         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11679         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11680     }
11681 
11682     @Test
11683     public void fixMediaNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible()
11684             throws Exception {
11685         // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set,
11686         // but has the flag FLAG_NO_DISMISS set
11687         Notification n = new Notification.Builder(mContext, "test")
11688                 .setOngoing(false)
11689                 .setStyle(new Notification.MediaStyle()
11690                         .setMediaSession(mock(MediaSession.Token.class)))
11691                 .build();
11692         n.flags |= Notification.FLAG_NO_DISMISS;
11693 
11694         // When: fix the notification with NotificationManagerService
11695         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11696 
11697         // Then: the notification's flag FLAG_NO_DISMISS should be cleared
11698         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11699     }
11700 
11701     @Test
11702     public void fixNonExempt_Notification_withoutOnGoingFlag_shouldBeDismissible()
11703             throws Exception {
11704         // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
11705         Notification n = new Notification.Builder(mContext, "test")
11706                 .setOngoing(false)
11707                 .build();
11708 
11709         // When: fix the notification with NotificationManagerService
11710         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11711 
11712         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11713         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11714     }
11715 
11716     @Test
11717     public void fixOrganizationAdminNotification_withOnGoingFlag_shouldBeNonDismissible()
11718             throws Exception {
11719         when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true);
11720         // Given: a notification has the flag FLAG_ONGOING_EVENT set
11721         setDpmAppOppsExemptFromDismissal(false);
11722         Notification n = new Notification.Builder(mContext, "test")
11723                 .setOngoing(true)
11724                 .build();
11725 
11726         // When: fix the notification with NotificationManagerService
11727         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11728 
11729         // Then: the notification's flag FLAG_NO_DISMISS should be set
11730         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11731     }
11732 
11733     @Test
11734     public void fixExemptAppOpNotification_withFlag_shouldBeNonDismissible()
11735             throws Exception {
11736         final ApplicationInfo ai = new ApplicationInfo();
11737         ai.packageName = PKG;
11738         ai.uid = mUid;
11739         ai.flags |= ApplicationInfo.FLAG_SYSTEM;
11740 
11741         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11742                 .thenReturn(ai);
11743         when(mAppOpsManager.checkOpNoThrow(
11744                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
11745                 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
11746         // Given: a notification has the flag FLAG_ONGOING_EVENT set
11747         setDpmAppOppsExemptFromDismissal(true);
11748         Notification n = new Notification.Builder(mContext, "test")
11749                 .setOngoing(true)
11750                 .build();
11751 
11752         // When: fix the notification with NotificationManagerService
11753         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11754 
11755         // Then: the notification's flag FLAG_NO_DISMISS should be cleared
11756         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11757     }
11758 
11759     @Test
11760     public void fixExemptAppOpNotification_withoutAppOpsFlag_shouldBeDismissible()
11761             throws Exception {
11762         when(mAppOpsManager.checkOpNoThrow(
11763                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
11764                 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
11765         // Given: a notification has the flag FLAG_ONGOING_EVENT set
11766         setDpmAppOppsExemptFromDismissal(false);
11767         Notification n = new Notification.Builder(mContext, "test")
11768                 .setOngoing(true)
11769                 .build();
11770 
11771         // When: fix the notification with NotificationManagerService
11772         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11773 
11774         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11775         assertSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11776     }
11777 
11778     @Test
11779     public void testCancelAllNotifications_IgnoreUserInitiatedJob() throws Exception {
11780         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11781                 .thenReturn(true);
11782         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11783         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11784         mBinderService.enqueueNotificationWithTag(PKG, PKG,
11785                 "testCancelAllNotifications_IgnoreUserInitiatedJob",
11786                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11787         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
11788         waitForIdle();
11789         StatusBarNotification[] notifs =
11790                 mBinderService.getActiveNotifications(sbn.getPackageName());
11791         assertEquals(1, notifs.length);
11792         assertEquals(1, mService.getNotificationRecordCount());
11793     }
11794 
11795     @Test
11796     public void testCancelAllNotifications_UijFlag_NoUij_Allowed() throws Exception {
11797         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11798                 .thenReturn(false);
11799         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11800         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11801         mBinderService.enqueueNotificationWithTag(PKG, PKG,
11802                 "testCancelAllNotifications_UijFlag_NoUij_Allowed",
11803                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11804         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
11805         waitForIdle();
11806         StatusBarNotification[] notifs =
11807                 mBinderService.getActiveNotifications(sbn.getPackageName());
11808         assertEquals(0, notifs.length);
11809     }
11810 
11811     @Test
11812     public void testCancelAllNotificationsOtherPackage_IgnoresUijNotification() throws Exception {
11813         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11814                 .thenReturn(true);
11815         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11816         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11817         mBinderService.enqueueNotificationWithTag(PKG, PKG,
11818                 "testCancelAllNotifications_IgnoreOtherPackages",
11819                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11820         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
11821         waitForIdle();
11822         StatusBarNotification[] notifs =
11823                 mBinderService.getActiveNotifications(sbn.getPackageName());
11824         assertEquals(1, notifs.length);
11825         assertEquals(1, mService.getNotificationRecordCount());
11826     }
11827 
11828     @Test
11829     public void testRemoveUserInitiatedJobFlag_ImmediatelyAfterEnqueue() throws Exception {
11830         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11831                 .thenReturn(true);
11832         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
11833                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
11834                 .build();
11835         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
11836                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11837         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11838         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
11839                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11840         mInternalService.removeUserInitiatedJobFlagFromNotification(PKG, sbn.getId(),
11841                 sbn.getUserId());
11842         waitForIdle();
11843         StatusBarNotification[] notifs =
11844                 mBinderService.getActiveNotifications(sbn.getPackageName());
11845         assertFalse(notifs[0].getNotification().isUserInitiatedJob());
11846     }
11847 
11848     @Test
11849     public void testCancelAfterSecondEnqueueDoesNotSpecifyUserInitiatedJobFlag() throws Exception {
11850         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11851         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT | FLAG_USER_INITIATED_JOB;
11852         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
11853                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11854         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
11855         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
11856                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11857         mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
11858                 sbn.getUserId());
11859         waitForIdle();
11860         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
11861         assertEquals(0, mService.getNotificationRecordCount());
11862     }
11863 
11864     @Test
11865     public void testCancelNotificationWithTag_fromApp_cannotCancelUijChild() throws Exception {
11866         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11867                 .thenReturn(true);
11868         mService.isSystemUid = false;
11869         mService.isSystemAppId = false;
11870         final NotificationRecord parent = generateNotificationRecord(
11871                 mTestNotificationChannel, 1, "group", true);
11872         final NotificationRecord child = generateNotificationRecord(
11873                 mTestNotificationChannel, 2, "group", false);
11874         final NotificationRecord child2 = generateNotificationRecord(
11875                 mTestNotificationChannel, 3, "group", false);
11876         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11877         mService.addNotification(parent);
11878         mService.addNotification(child);
11879         mService.addNotification(child2);
11880         mService.getBinderService().cancelNotificationWithTag(
11881                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
11882                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
11883         waitForIdle();
11884         StatusBarNotification[] notifs =
11885                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11886         assertEquals(1, notifs.length);
11887     }
11888 
11889     @Test
11890     public void testCancelNotificationWithTag_fromApp_cannotCancelUijParent() throws Exception {
11891         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11892                 .thenReturn(true);
11893         mService.isSystemUid = false;
11894         mService.isSystemAppId = false;
11895         final NotificationRecord parent = generateNotificationRecord(
11896                 mTestNotificationChannel, 1, "group", true);
11897         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11898         final NotificationRecord child = generateNotificationRecord(
11899                 mTestNotificationChannel, 2, "group", false);
11900         final NotificationRecord child2 = generateNotificationRecord(
11901                 mTestNotificationChannel, 3, "group", false);
11902         mService.addNotification(parent);
11903         mService.addNotification(child);
11904         mService.addNotification(child2);
11905         mService.getBinderService().cancelNotificationWithTag(
11906                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
11907                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
11908         waitForIdle();
11909         StatusBarNotification[] notifs =
11910                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11911         assertEquals(3, notifs.length);
11912     }
11913 
11914     @Test
11915     public void testCancelAllNotificationsFromApp_cannotCancelUijChild() throws Exception {
11916         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11917                 .thenReturn(true);
11918         mService.isSystemUid = false;
11919         mService.isSystemAppId = false;
11920         final NotificationRecord parent = generateNotificationRecord(
11921                 mTestNotificationChannel, 1, "group", true);
11922         final NotificationRecord child = generateNotificationRecord(
11923                 mTestNotificationChannel, 2, "group", false);
11924         final NotificationRecord child2 = generateNotificationRecord(
11925                 mTestNotificationChannel, 3, "group", false);
11926         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11927         final NotificationRecord newGroup = generateNotificationRecord(
11928                 mTestNotificationChannel, 4, "group2", false);
11929         mService.addNotification(parent);
11930         mService.addNotification(child);
11931         mService.addNotification(child2);
11932         mService.addNotification(newGroup);
11933         mService.getBinderService().cancelAllNotifications(
11934                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
11935         waitForIdle();
11936         StatusBarNotification[] notifs =
11937                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11938         assertEquals(1, notifs.length);
11939     }
11940 
11941     @Test
11942     public void testCancelAllNotifications_fromApp_cannotCancelUijParent() throws Exception {
11943         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11944                 .thenReturn(true);
11945         mService.isSystemUid = false;
11946         mService.isSystemAppId = false;
11947         final NotificationRecord parent = generateNotificationRecord(
11948                 mTestNotificationChannel, 1, "group", true);
11949         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11950         final NotificationRecord child = generateNotificationRecord(
11951                 mTestNotificationChannel, 2, "group", false);
11952         final NotificationRecord child2 = generateNotificationRecord(
11953                 mTestNotificationChannel, 3, "group", false);
11954         final NotificationRecord newGroup = generateNotificationRecord(
11955                 mTestNotificationChannel, 4, "group2", false);
11956         mService.addNotification(parent);
11957         mService.addNotification(child);
11958         mService.addNotification(child2);
11959         mService.addNotification(newGroup);
11960         mService.getBinderService().cancelAllNotifications(
11961                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
11962         waitForIdle();
11963         StatusBarNotification[] notifs =
11964                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11965         assertEquals(1, notifs.length);
11966     }
11967 
11968     @Test
11969     public void testCancelNotificationsFromListener_clearAll_GroupWithUijParent() throws Exception {
11970         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11971                 .thenReturn(true);
11972         final NotificationRecord parent = generateNotificationRecord(
11973                 mTestNotificationChannel, 1, "group", true);
11974         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11975         final NotificationRecord child = generateNotificationRecord(
11976                 mTestNotificationChannel, 2, "group", false);
11977         final NotificationRecord child2 = generateNotificationRecord(
11978                 mTestNotificationChannel, 3, "group", false);
11979         final NotificationRecord newGroup = generateNotificationRecord(
11980                 mTestNotificationChannel, 4, "group2", false);
11981         mService.addNotification(parent);
11982         mService.addNotification(child);
11983         mService.addNotification(child2);
11984         mService.addNotification(newGroup);
11985         mService.getBinderService().cancelNotificationsFromListener(null, null);
11986         waitForIdle();
11987         StatusBarNotification[] notifs =
11988                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11989         assertEquals(0, notifs.length);
11990     }
11991 
11992     @Test
11993     public void testCancelNotificationsFromListener_clearAll_GroupWithUijChild() throws Exception {
11994         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11995                 .thenReturn(true);
11996         final NotificationRecord parent = generateNotificationRecord(
11997                 mTestNotificationChannel, 1, "group", true);
11998         final NotificationRecord child = generateNotificationRecord(
11999                 mTestNotificationChannel, 2, "group", false);
12000         final NotificationRecord child2 = generateNotificationRecord(
12001                 mTestNotificationChannel, 3, "group", false);
12002         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12003         final NotificationRecord newGroup = generateNotificationRecord(
12004                 mTestNotificationChannel, 4, "group2", false);
12005         mService.addNotification(parent);
12006         mService.addNotification(child);
12007         mService.addNotification(child2);
12008         mService.addNotification(newGroup);
12009         mService.getBinderService().cancelNotificationsFromListener(null, null);
12010         waitForIdle();
12011         StatusBarNotification[] notifs =
12012                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
12013         assertEquals(0, notifs.length);
12014     }
12015 
12016     @Test
12017     public void testCancelNotificationsFromListener_clearAll_Uij() throws Exception {
12018         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12019                 .thenReturn(true);
12020         final NotificationRecord child2 = generateNotificationRecord(
12021                 mTestNotificationChannel, 3, null, false);
12022         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12023         mService.addNotification(child2);
12024         mService.getBinderService().cancelNotificationsFromListener(null, null);
12025         waitForIdle();
12026         StatusBarNotification[] notifs =
12027                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
12028         assertEquals(0, notifs.length);
12029     }
12030 
12031     @Test
12032     public void testCancelNotificationsFromListener_byKey_GroupWithUijParent() throws Exception {
12033         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12034                 .thenReturn(true);
12035         final NotificationRecord parent = generateNotificationRecord(
12036                 mTestNotificationChannel, 1, "group", true);
12037         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12038         final NotificationRecord child = generateNotificationRecord(
12039                 mTestNotificationChannel, 2, "group", false);
12040         final NotificationRecord child2 = generateNotificationRecord(
12041                 mTestNotificationChannel, 3, "group", false);
12042         final NotificationRecord newGroup = generateNotificationRecord(
12043                 mTestNotificationChannel, 4, "group2", false);
12044         mService.addNotification(parent);
12045         mService.addNotification(child);
12046         mService.addNotification(child2);
12047         mService.addNotification(newGroup);
12048         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
12049                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
12050         mService.getBinderService().cancelNotificationsFromListener(null, keys);
12051         waitForIdle();
12052         StatusBarNotification[] notifs =
12053                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
12054         assertEquals(0, notifs.length);
12055     }
12056 
12057     @Test
12058     public void testCancelNotificationsFromListener_byKey_GroupWithUijChild() throws Exception {
12059         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12060                 .thenReturn(true);
12061         final NotificationRecord parent = generateNotificationRecord(
12062                 mTestNotificationChannel, 1, "group", true);
12063         final NotificationRecord child = generateNotificationRecord(
12064                 mTestNotificationChannel, 2, "group", false);
12065         final NotificationRecord child2 = generateNotificationRecord(
12066                 mTestNotificationChannel, 3, "group", false);
12067         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12068         final NotificationRecord newGroup = generateNotificationRecord(
12069                 mTestNotificationChannel, 4, "group2", false);
12070         mService.addNotification(parent);
12071         mService.addNotification(child);
12072         mService.addNotification(child2);
12073         mService.addNotification(newGroup);
12074         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
12075                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
12076         mService.getBinderService().cancelNotificationsFromListener(null, keys);
12077         waitForIdle();
12078         StatusBarNotification[] notifs =
12079                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
12080         assertEquals(0, notifs.length);
12081     }
12082 
12083     @Test
12084     public void testCancelNotificationsFromListener_byKey_Uij() throws Exception {
12085         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12086                 .thenReturn(true);
12087         final NotificationRecord child = generateNotificationRecord(
12088                 mTestNotificationChannel, 3, null, false);
12089         child.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12090         mService.addNotification(child);
12091         String[] keys = {child.getSbn().getKey()};
12092         mService.getBinderService().cancelNotificationsFromListener(null, keys);
12093         waitForIdle();
12094         StatusBarNotification[] notifs =
12095                 mBinderService.getActiveNotifications(child.getSbn().getPackageName());
12096         assertEquals(0, notifs.length);
12097     }
12098 
12099     @Test
12100     public void testUserInitiatedCancelAllWithGroup_UserInitiatedFlag() throws Exception {
12101         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12102                 .thenReturn(true);
12103         final NotificationRecord parent = generateNotificationRecord(
12104                 mTestNotificationChannel, 1, "group", true);
12105         final NotificationRecord child = generateNotificationRecord(
12106                 mTestNotificationChannel, 2, "group", false);
12107         final NotificationRecord child2 = generateNotificationRecord(
12108                 mTestNotificationChannel, 3, "group", false);
12109         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12110         final NotificationRecord newGroup = generateNotificationRecord(
12111                 mTestNotificationChannel, 4, "group2", false);
12112         mService.addNotification(parent);
12113         mService.addNotification(child);
12114         mService.addNotification(child2);
12115         mService.addNotification(newGroup);
12116         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId());
12117         waitForIdle();
12118         StatusBarNotification[] notifs =
12119                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
12120         assertEquals(0, notifs.length);
12121     }
12122 
12123     @Test
12124     public void testDeleteChannelGroupChecksForUijs() throws Exception {
12125         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
12126                 .thenReturn(singletonList(mock(AssociationInfo.class)));
12127         CountDownLatch latch = new CountDownLatch(2);
12128         mService.createNotificationChannelGroup(PKG, mUid,
12129                 new NotificationChannelGroup("group", "group"), true, false);
12130         new Thread(() -> {
12131             NotificationChannel notificationChannel = new NotificationChannel("id", "id",
12132                     NotificationManager.IMPORTANCE_HIGH);
12133             notificationChannel.setGroup("group");
12134             ParceledListSlice<NotificationChannel> pls =
12135                     new ParceledListSlice(ImmutableList.of(notificationChannel));
12136             try {
12137                 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
12138             } catch (RemoteException e) {
12139                 throw new RuntimeException(e);
12140             }
12141             latch.countDown();
12142         }).start();
12143         new Thread(() -> {
12144             try {
12145                 synchronized (this) {
12146                     wait(5000);
12147                 }
12148                 mService.createNotificationChannelGroup(PKG, mUid,
12149                         new NotificationChannelGroup("new", "new group"), true, false);
12150                 NotificationChannel notificationChannel =
12151                         new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
12152                 notificationChannel.setGroup("new");
12153                 ParceledListSlice<NotificationChannel> pls =
12154                         new ParceledListSlice(ImmutableList.of(notificationChannel));
12155                 try {
12156                     mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
12157                     mBinderService.deleteNotificationChannelGroup(PKG, "group");
12158                 } catch (RemoteException e) {
12159                     throw new RuntimeException(e);
12160                 }
12161             } catch (Exception e) {
12162                 e.printStackTrace();
12163             }
12164             latch.countDown();
12165         }).start();
12166 
12167         latch.await();
12168         verify(mJsi).isNotificationChannelAssociatedWithAnyUserInitiatedJobs(
12169                 anyString(), anyInt(), anyString());
12170     }
12171 
12172     @Test
12173     public void testRemoveUserInitiatedJobFlagFromNotification_enqueued() {
12174         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12175                 .thenReturn(true);
12176         Notification n = new Notification.Builder(mContext, "").build();
12177         n.flags |= FLAG_USER_INITIATED_JOB;
12178 
12179         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
12180                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12181         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12182 
12183         mService.addEnqueuedNotification(r);
12184 
12185         mInternalService.removeUserInitiatedJobFlagFromNotification(
12186                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12187 
12188         waitForIdle();
12189 
12190         verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
12191     }
12192 
12193     @Test
12194     public void testRemoveUserInitiatedJobFlagFromNotification_posted() {
12195         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12196                 .thenReturn(true);
12197         Notification n = new Notification.Builder(mContext, "").build();
12198         n.flags |= FLAG_USER_INITIATED_JOB;
12199 
12200         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
12201                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12202         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12203 
12204         mService.addNotification(r);
12205 
12206         mInternalService.removeUserInitiatedJobFlagFromNotification(
12207                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12208 
12209         waitForIdle();
12210 
12211         ArgumentCaptor<NotificationRecord> captor =
12212                 ArgumentCaptor.forClass(NotificationRecord.class);
12213         verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
12214 
12215         assertEquals(0, captor.getValue().getNotification().flags);
12216     }
12217 
12218     @Test
12219     public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_enqueued() {
12220         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12221             Notification n = new Notification.Builder(mContext, "").build();
12222             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
12223                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
12224             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12225             mService.addEnqueuedNotification(r);
12226         }
12227         Notification n = new Notification.Builder(mContext, "").build();
12228         n.flags |= FLAG_USER_INITIATED_JOB;
12229 
12230         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
12231                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
12232                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12233         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12234 
12235         mService.addEnqueuedNotification(r);
12236 
12237         mInternalService.removeUserInitiatedJobFlagFromNotification(
12238                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12239 
12240         waitForIdle();
12241 
12242         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
12243                 mService.getNotificationRecordCount());
12244     }
12245 
12246     @Test
12247     public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_posted() {
12248         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12249                 .thenReturn(true);
12250         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12251             Notification n = new Notification.Builder(mContext, "").build();
12252             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
12253                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
12254             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12255             mService.addNotification(r);
12256         }
12257         Notification n = new Notification.Builder(mContext, "").build();
12258         n.flags |= FLAG_USER_INITIATED_JOB;
12259 
12260         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
12261                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
12262                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12263         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12264 
12265         mService.addNotification(r);
12266 
12267         mInternalService.removeUserInitiatedJobFlagFromNotification(
12268                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12269 
12270         waitForIdle();
12271 
12272         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
12273                 mService.getNotificationRecordCount());
12274     }
12275 
12276     @Test
12277     public void testCanPostUijWhenOverLimit() throws RemoteException {
12278         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12279                 .thenReturn(true);
12280         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12281             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
12282                     i, null, false).getSbn();
12283             mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCanPostUijWhenOverLimit",
12284                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
12285         }
12286 
12287         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
12288         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12289         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12290                 "testCanPostUijWhenOverLimit - uij over limit!",
12291                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
12292 
12293         waitForIdle();
12294 
12295         StatusBarNotification[] notifs =
12296                 mBinderService.getActiveNotifications(sbn.getPackageName());
12297         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
12298         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
12299                 mService.getNotificationRecordCount());
12300     }
12301 
12302     @Test
12303     public void testCannotPostNonUijWhenOverLimit() throws RemoteException {
12304         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12305                 .thenReturn(true);
12306         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12307             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
12308                     i, null, false).getSbn();
12309             mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCannotPostNonUijWhenOverLimit",
12310                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
12311             waitForIdle();
12312         }
12313 
12314         final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
12315                 100, null, false).getSbn();
12316         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12317         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12318                 "testCannotPostNonUijWhenOverLimit - uij over limit!",
12319                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
12320 
12321         final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
12322                 101, null, false).getSbn();
12323         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12324                 "testCannotPostNonUijWhenOverLimit - non uij over limit!",
12325                 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
12326 
12327         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12328                 .thenReturn(false);
12329         final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel,
12330                 101, null, false).getSbn();
12331         sbn3.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12332         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12333                 "testCannotPostNonUijWhenOverLimit - fake uij over limit!",
12334                 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId());
12335 
12336         waitForIdle();
12337 
12338         StatusBarNotification[] notifs =
12339                 mBinderService.getActiveNotifications(sbn.getPackageName());
12340         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
12341         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
12342                 mService.getNotificationRecordCount());
12343     }
12344 
12345     @Test
12346     public void fixNotification_withUijFlag_butIsNotUij() throws Exception {
12347         final ApplicationInfo applicationInfo = new ApplicationInfo();
12348         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
12349                 .thenReturn(applicationInfo);
12350 
12351         Notification n = new Notification.Builder(mContext, "test")
12352                 .setFlag(FLAG_USER_INITIATED_JOB, true)
12353                 .build();
12354 
12355         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
12356         assertFalse(n.isUserInitiatedJob());
12357     }
12358 
12359     @Test
12360     public void enqueue_updatesEnqueueRate() throws Exception {
12361         Notification n = generateNotificationRecord(null).getNotification();
12362 
12363         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
12364         // Don't waitForIdle() here. We want to verify the "intermediate" state.
12365 
12366         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12367         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12368         verify(mUsageStats, never()).registerPostedByApp(any());
12369 
12370         waitForIdle();
12371     }
12372 
12373     @Test
12374     public void enqueue_withPost_updatesEnqueueRateAndPost() throws Exception {
12375         Notification n = generateNotificationRecord(null).getNotification();
12376 
12377         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
12378         waitForIdle();
12379 
12380         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12381         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12382         verify(mUsageStats).registerPostedByApp(any());
12383     }
12384 
12385     @Test
12386     public void enqueueNew_whenOverEnqueueRate_accepts() throws Exception {
12387         Notification n = generateNotificationRecord(null).getNotification();
12388         when(mUsageStats.getAppEnqueueRate(eq(PKG)))
12389                 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f);
12390 
12391         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
12392         waitForIdle();
12393 
12394         assertThat(mService.mNotificationsByKey).hasSize(1);
12395         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12396         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12397         verify(mUsageStats).registerPostedByApp(any());
12398     }
12399 
12400     @Test
12401     public void enqueueUpdate_whenBelowMaxEnqueueRate_accepts() throws Exception {
12402         // Post the first version.
12403         Notification original = generateNotificationRecord(null).getNotification();
12404         original.when = 111;
12405         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId);
12406         waitForIdle();
12407         assertThat(mService.mNotificationList).hasSize(1);
12408         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111);
12409 
12410         reset(mUsageStats);
12411         when(mUsageStats.getAppEnqueueRate(eq(PKG)))
12412                 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE - 1f);
12413 
12414         // Post the update.
12415         Notification update = generateNotificationRecord(null).getNotification();
12416         update.when = 222;
12417         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId);
12418         waitForIdle();
12419 
12420         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12421         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12422         verify(mUsageStats, never()).registerPostedByApp(any());
12423         verify(mUsageStats).registerUpdatedByApp(any(), any());
12424         assertThat(mService.mNotificationList).hasSize(1);
12425         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(222);
12426     }
12427 
12428     @Test
12429     public void enqueueUpdate_whenAboveMaxEnqueueRate_rejects() throws Exception {
12430         // Post the first version.
12431         Notification original = generateNotificationRecord(null).getNotification();
12432         original.when = 111;
12433         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId);
12434         waitForIdle();
12435         assertThat(mService.mNotificationList).hasSize(1);
12436         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111);
12437 
12438         reset(mUsageStats);
12439         when(mUsageStats.getAppEnqueueRate(eq(PKG)))
12440                 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f);
12441 
12442         // Post the update.
12443         Notification update = generateNotificationRecord(null).getNotification();
12444         update.when = 222;
12445         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId);
12446         waitForIdle();
12447 
12448         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12449         verify(mUsageStats, never()).registerEnqueuedByAppAndAccepted(any());
12450         verify(mUsageStats, never()).registerPostedByApp(any());
12451         verify(mUsageStats, never()).registerUpdatedByApp(any(), any());
12452         assertThat(mService.mNotificationList).hasSize(1);
12453         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); // old
12454     }
12455 
12456     @Test
12457     public void enqueueNotification_allowlistsPendingIntents() throws RemoteException {
12458         PendingIntent contentIntent = createPendingIntent("content");
12459         PendingIntent actionIntent1 = createPendingIntent("action1");
12460         PendingIntent actionIntent2 = createPendingIntent("action2");
12461         Notification n = new Notification.Builder(mContext, TEST_CHANNEL_ID)
12462                 .setContentIntent(contentIntent)
12463                 .addAction(new Notification.Action.Builder(null, "action1", actionIntent1).build())
12464                 .addAction(new Notification.Action.Builder(null, "action2", actionIntent2).build())
12465                 .build();
12466 
12467         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1,
12468                 parcelAndUnparcel(n, Notification.CREATOR), mUserId);
12469 
12470         verify(mAmi, times(3)).setPendingIntentAllowlistDuration(
12471                 any(), any(), anyLong(),
12472                 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED),
12473                 eq(REASON_NOTIFICATION_SERVICE), any());
12474         verify(mAmi, times(3)).setPendingIntentAllowBgActivityStarts(any(),
12475                 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
12476     }
12477 
12478     @Test
12479     public void enqueueNotification_allowlistsPendingIntents_includingFromPublicVersion()
12480             throws RemoteException {
12481         PendingIntent contentIntent = createPendingIntent("content");
12482         PendingIntent actionIntent = createPendingIntent("action");
12483         PendingIntent publicContentIntent = createPendingIntent("publicContent");
12484         PendingIntent publicActionIntent = createPendingIntent("publicAction");
12485         Notification source = new Notification.Builder(mContext, TEST_CHANNEL_ID)
12486                 .setContentIntent(contentIntent)
12487                 .addAction(new Notification.Action.Builder(null, "action", actionIntent).build())
12488                 .setPublicVersion(new Notification.Builder(mContext, "channel")
12489                         .setContentIntent(publicContentIntent)
12490                         .addAction(new Notification.Action.Builder(
12491                                 null, "publicAction", publicActionIntent).build())
12492                         .build())
12493                 .build();
12494 
12495         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1,
12496                 parcelAndUnparcel(source, Notification.CREATOR), mUserId);
12497 
12498         verify(mAmi, times(4)).setPendingIntentAllowlistDuration(
12499                 any(), any(), anyLong(),
12500                 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED),
12501                 eq(REASON_NOTIFICATION_SERVICE), any());
12502         verify(mAmi, times(4)).setPendingIntentAllowBgActivityStarts(any(),
12503                 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
12504     }
12505 
12506     @Test
12507     public void onUserSwitched_updatesZenModeAndChannelsBypassingDnd() {
12508         Intent intent = new Intent(Intent.ACTION_USER_SWITCHED);
12509         intent.putExtra(Intent.EXTRA_USER_HANDLE, 20);
12510         mService.mZenModeHelper = mock(ZenModeHelper.class);
12511         mService.setPreferencesHelper(mPreferencesHelper);
12512 
12513         mUserSwitchIntentReceiver.onReceive(mContext, intent);
12514 
12515         InOrder inOrder = inOrder(mPreferencesHelper, mService.mZenModeHelper);
12516         inOrder.verify(mService.mZenModeHelper).onUserSwitched(eq(20));
12517         inOrder.verify(mPreferencesHelper).syncChannelsBypassingDnd();
12518         inOrder.verifyNoMoreInteractions();
12519     }
12520 
12521     @Test
12522     public void isNotificationPolicyAccessGranted_invalidPackage() throws Exception {
12523         final String notReal = "NOT REAL";
12524         final var checker = mService.permissionChecker;
12525 
12526         when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
12527                 PackageManager.NameNotFoundException.class);
12528 
12529         assertThat(mBinderService.isNotificationPolicyAccessGranted(notReal)).isFalse();
12530         verify(mPackageManagerClient).getPackageUidAsUser(eq(notReal), anyInt());
12531         verify(checker, never()).check(any(), anyInt(), anyInt(), anyBoolean());
12532         verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(notReal), anyInt());
12533         verify(mListeners, never()).isComponentEnabledForPackage(any());
12534         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12535     }
12536 
12537     @Test
12538     public void isNotificationPolicyAccessGranted_hasPermission() throws Exception {
12539         final String packageName = "target";
12540         final int uid = 123;
12541         final var checker = mService.permissionChecker;
12542 
12543         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12544         when(checker.check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true))
12545                 .thenReturn(PackageManager.PERMISSION_GRANTED);
12546 
12547         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12548         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12549         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12550         verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(packageName), anyInt());
12551         verify(mListeners, never()).isComponentEnabledForPackage(any());
12552         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12553     }
12554 
12555     @Test
12556     public void isNotificationPolicyAccessGranted_isPackageAllowed() throws Exception {
12557         final String packageName = "target";
12558         final int uid = 123;
12559         final var checker = mService.permissionChecker;
12560 
12561         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12562         when(mConditionProviders.isPackageOrComponentAllowed(eq(packageName), anyInt()))
12563                 .thenReturn(true);
12564 
12565         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12566         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12567         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12568         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12569         verify(mListeners, never()).isComponentEnabledForPackage(any());
12570         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12571     }
12572 
12573     @Test
12574     public void isNotificationPolicyAccessGranted_isComponentEnabled() throws Exception {
12575         final String packageName = "target";
12576         final int uid = 123;
12577         final var checker = mService.permissionChecker;
12578 
12579         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12580         when(mListeners.isComponentEnabledForPackage(packageName)).thenReturn(true);
12581 
12582         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12583         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12584         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12585         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12586         verify(mListeners).isComponentEnabledForPackage(packageName);
12587         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12588     }
12589 
12590     @Test
12591     public void isNotificationPolicyAccessGranted_isDeviceOwner() throws Exception {
12592         final String packageName = "target";
12593         final int uid = 123;
12594         final var checker = mService.permissionChecker;
12595 
12596         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12597         when(mDevicePolicyManager.isActiveDeviceOwner(uid)).thenReturn(true);
12598 
12599         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12600         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12601         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12602         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12603         verify(mListeners).isComponentEnabledForPackage(packageName);
12604         verify(mDevicePolicyManager).isActiveDeviceOwner(uid);
12605     }
12606 
12607     /**
12608      * b/292163859
12609      */
12610     @Test
12611     public void isNotificationPolicyAccessGranted_callerIsDeviceOwner() throws Exception {
12612         final String packageName = "target";
12613         final int uid = 123;
12614         final int callingUid = Binder.getCallingUid();
12615         final var checker = mService.permissionChecker;
12616 
12617         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12618         when(mDevicePolicyManager.isActiveDeviceOwner(callingUid)).thenReturn(true);
12619 
12620         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse();
12621         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12622         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12623         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12624         verify(mListeners).isComponentEnabledForPackage(packageName);
12625         verify(mDevicePolicyManager).isActiveDeviceOwner(uid);
12626         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(callingUid);
12627     }
12628 
12629     @Test
12630     public void isNotificationPolicyAccessGranted_notGranted() throws Exception {
12631         final String packageName = "target";
12632         final int uid = 123;
12633         final var checker = mService.permissionChecker;
12634 
12635         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12636 
12637         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse();
12638         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12639         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12640         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12641         verify(mListeners).isComponentEnabledForPackage(packageName);
12642         verify(mDevicePolicyManager).isActiveDeviceOwner(uid);
12643     }
12644 
12645     private static <T extends Parcelable> T parcelAndUnparcel(T source,
12646             Parcelable.Creator<T> creator) {
12647         Parcel parcel = Parcel.obtain();
12648         source.writeToParcel(parcel, 0);
12649         parcel.setDataPosition(0);
12650         return creator.createFromParcel(parcel);
12651     }
12652 
12653     private PendingIntent createPendingIntent(String action) {
12654         return PendingIntent.getActivity(mContext, 0,
12655                 new Intent(action).setPackage(mContext.getPackageName()),
12656                 PendingIntent.FLAG_MUTABLE);
12657     }
12658 
12659     private void setDpmAppOppsExemptFromDismissal(boolean isOn) {
12660         DeviceConfig.setProperty(
12661                 DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
12662                 /* name= */ "application_exemptions",
12663                 String.valueOf(isOn),
12664                 /* makeDefault= */ false);
12665     }
12666 
12667     private void allowTestPackageToToast() throws Exception {
12668         assertWithMessage("toast queue").that(mService.mToastQueue).isEmpty();
12669         mService.isSystemUid = false;
12670         mService.isSystemAppId = false;
12671         setToastRateIsWithinQuota(true);
12672         setIfPackageHasPermissionToAvoidToastRateLimiting(TEST_PACKAGE, false);
12673         // package is not suspended
12674         when(mPackageManager.isPackageSuspendedForUser(TEST_PACKAGE, mUserId))
12675                 .thenReturn(false);
12676     }
12677 
12678     private void enqueueToast(String testPackage, ITransientNotification callback)
12679             throws RemoteException {
12680         enqueueToast((INotificationManager) mService.mService, testPackage, new Binder(), callback);
12681     }
12682 
12683     private void enqueueToast(INotificationManager service, String testPackage,
12684             IBinder token, ITransientNotification callback) throws RemoteException {
12685         service.enqueueToast(testPackage, token, callback, TOAST_DURATION, /* isUiContext= */ true,
12686                 DEFAULT_DISPLAY);
12687     }
12688 
12689     private void enqueueTextToast(String testPackage, CharSequence text) throws RemoteException {
12690         enqueueTextToast(testPackage, text, /* isUiContext= */ true, DEFAULT_DISPLAY);
12691     }
12692 
12693     private void enqueueTextToast(String testPackage, CharSequence text, boolean isUiContext,
12694             int displayId) throws RemoteException {
12695         ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), text,
12696                 TOAST_DURATION, isUiContext, displayId, /* textCallback= */ null);
12697     }
12698 
12699     private void mockIsVisibleBackgroundUsersSupported(boolean supported) {
12700         when(mUm.isVisibleBackgroundUsersSupported()).thenReturn(supported);
12701     }
12702 
12703     private void mockIsUserVisible(int displayId, boolean visible) {
12704         when(mUmInternal.isUserVisible(mUserId, displayId)).thenReturn(visible);
12705     }
12706 
12707     private void mockDisplayAssignedToUser(int displayId) {
12708         when(mUmInternal.getMainDisplayAssignedToUser(mUserId)).thenReturn(displayId);
12709     }
12710 
12711     private void verifyToastShownForTestPackage(String text, int displayId) {
12712         verify(mStatusBar).showToast(eq(mUid), eq(TEST_PACKAGE), any(), eq(text), any(),
12713                 eq(TOAST_DURATION), any(), eq(displayId));
12714     }
12715 }
12716