• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.notification;
18 
19 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
21 import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
22 import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY;
23 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
24 import static android.app.Notification.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.assertThrows;
109 import static org.mockito.ArgumentMatchers.isNull;
110 import static org.mockito.Matchers.anyBoolean;
111 import static org.mockito.Matchers.anyLong;
112 import static org.mockito.Matchers.anyString;
113 import static org.mockito.Matchers.eq;
114 import static org.mockito.Mockito.any;
115 import static org.mockito.Mockito.anyInt;
116 import static org.mockito.Mockito.atLeastOnce;
117 import static org.mockito.Mockito.clearInvocations;
118 import static org.mockito.Mockito.doAnswer;
119 import static org.mockito.Mockito.doNothing;
120 import static org.mockito.Mockito.doThrow;
121 import static org.mockito.Mockito.inOrder;
122 import static org.mockito.Mockito.mock;
123 import static org.mockito.Mockito.never;
124 import static org.mockito.Mockito.reset;
125 import static org.mockito.Mockito.spy;
126 import static org.mockito.Mockito.timeout;
127 import static org.mockito.Mockito.times;
128 import static org.mockito.Mockito.verify;
129 import static org.mockito.Mockito.verifyNoMoreInteractions;
130 import static org.mockito.Mockito.verifyZeroInteractions;
131 import static org.mockito.Mockito.when;
132 
133 import static java.util.Collections.emptyList;
134 import static java.util.Collections.singletonList;
135 
136 import android.Manifest;
137 import android.annotation.Nullable;
138 import android.annotation.SuppressLint;
139 import android.annotation.UserIdInt;
140 import android.app.ActivityManager;
141 import android.app.ActivityManagerInternal;
142 import android.app.AlarmManager;
143 import android.app.AppOpsManager;
144 import android.app.AutomaticZenRule;
145 import android.app.IActivityManager;
146 import android.app.INotificationManager;
147 import android.app.ITransientNotification;
148 import android.app.IUriGrantsManager;
149 import android.app.Notification;
150 import android.app.Notification.MessagingStyle.Message;
151 import android.app.NotificationChannel;
152 import android.app.NotificationChannelGroup;
153 import android.app.NotificationManager;
154 import android.app.PendingIntent;
155 import android.app.Person;
156 import android.app.RemoteInput;
157 import android.app.RemoteInputHistoryItem;
158 import android.app.StatsManager;
159 import android.app.admin.DevicePolicyManagerInternal;
160 import android.app.usage.UsageStatsManagerInternal;
161 import android.companion.AssociationInfo;
162 import android.companion.ICompanionDeviceManager;
163 import android.content.BroadcastReceiver;
164 import android.content.ComponentName;
165 import android.content.ContentUris;
166 import android.content.Context;
167 import android.content.IIntentSender;
168 import android.content.Intent;
169 import android.content.IntentFilter;
170 import android.content.pm.ActivityInfo;
171 import android.content.pm.ApplicationInfo;
172 import android.content.pm.IPackageManager;
173 import android.content.pm.LauncherApps;
174 import android.content.pm.PackageManager;
175 import android.content.pm.PackageManagerInternal;
176 import android.content.pm.ParceledListSlice;
177 import android.content.pm.ShortcutInfo;
178 import android.content.pm.ShortcutServiceInternal;
179 import android.content.pm.UserInfo;
180 import android.content.pm.VersionedPackage;
181 import android.content.res.Resources;
182 import android.graphics.Color;
183 import android.graphics.drawable.Icon;
184 import android.media.AudioManager;
185 import android.media.IRingtonePlayer;
186 import android.media.session.MediaSession;
187 import android.net.Uri;
188 import android.os.Binder;
189 import android.os.Build;
190 import android.os.Bundle;
191 import android.os.IBinder;
192 import android.os.Looper;
193 import android.os.Parcel;
194 import android.os.Parcelable;
195 import android.os.PowerManager;
196 import android.os.PowerManager.WakeLock;
197 import android.os.Process;
198 import android.os.RemoteException;
199 import android.os.SystemClock;
200 import android.os.UserHandle;
201 import android.os.UserManager;
202 import android.os.WorkSource;
203 import android.permission.PermissionManager;
204 import android.provider.DeviceConfig;
205 import android.provider.MediaStore;
206 import android.provider.Settings;
207 import android.service.notification.Adjustment;
208 import android.service.notification.ConversationChannelWrapper;
209 import android.service.notification.NotificationListenerFilter;
210 import android.service.notification.NotificationListenerService;
211 import android.service.notification.NotificationRankingUpdate;
212 import android.service.notification.NotificationStats;
213 import android.service.notification.StatusBarNotification;
214 import android.service.notification.ZenPolicy;
215 import android.telecom.TelecomManager;
216 import android.telephony.TelephonyManager;
217 import android.test.suitebuilder.annotation.SmallTest;
218 import android.testing.AndroidTestingRunner;
219 import android.testing.TestableLooper;
220 import android.testing.TestableLooper.RunWithLooper;
221 import android.testing.TestablePermissions;
222 import android.testing.TestableResources;
223 import android.text.Html;
224 import android.text.TextUtils;
225 import android.util.ArrayMap;
226 import android.util.ArraySet;
227 import android.util.AtomicFile;
228 import android.util.Pair;
229 import android.util.Xml;
230 import android.widget.RemoteViews;
231 
232 import androidx.test.InstrumentationRegistry;
233 
234 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
235 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag;
236 import com.android.internal.config.sysui.TestableFlagResolver;
237 import com.android.internal.logging.InstanceIdSequence;
238 import com.android.internal.logging.InstanceIdSequenceFake;
239 import com.android.internal.messages.nano.SystemMessageProto;
240 import com.android.internal.statusbar.NotificationVisibility;
241 import com.android.modules.utils.TypedXmlPullParser;
242 import com.android.modules.utils.TypedXmlSerializer;
243 import com.android.server.DeviceIdleInternal;
244 import com.android.server.LocalServices;
245 import com.android.server.SystemService;
246 import com.android.server.SystemService.TargetUser;
247 import com.android.server.UiServiceTestCase;
248 import com.android.server.job.JobSchedulerInternal;
249 import com.android.server.lights.LightsManager;
250 import com.android.server.lights.LogicalLight;
251 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
252 import com.android.server.notification.NotificationManagerService.NotificationListeners;
253 import com.android.server.notification.NotificationManagerService.PostNotificationTracker;
254 import com.android.server.notification.NotificationManagerService.PostNotificationTrackerFactory;
255 import com.android.server.pm.PackageManagerService;
256 import com.android.server.pm.UserManagerInternal;
257 import com.android.server.policy.PermissionPolicyInternal;
258 import com.android.server.statusbar.StatusBarManagerInternal;
259 import com.android.server.uri.UriGrantsManagerInternal;
260 import com.android.server.utils.quota.MultiRateLimiter;
261 import com.android.server.wm.ActivityTaskManagerInternal;
262 import com.android.server.wm.WindowManagerInternal;
263 
264 import com.google.android.collect.Lists;
265 import com.google.common.collect.ImmutableList;
266 
267 import org.junit.After;
268 import org.junit.Assert;
269 import org.junit.Before;
270 import org.junit.Test;
271 import org.junit.runner.RunWith;
272 import org.mockito.ArgumentCaptor;
273 import org.mockito.ArgumentMatcher;
274 import org.mockito.ArgumentMatchers;
275 import org.mockito.InOrder;
276 import org.mockito.Mock;
277 import org.mockito.MockitoAnnotations;
278 import org.mockito.invocation.InvocationOnMock;
279 import org.mockito.stubbing.Answer;
280 
281 import java.io.BufferedInputStream;
282 import java.io.BufferedOutputStream;
283 import java.io.ByteArrayInputStream;
284 import java.io.ByteArrayOutputStream;
285 import java.io.File;
286 import java.io.FileOutputStream;
287 import java.util.ArrayList;
288 import java.util.Arrays;
289 import java.util.Collections;
290 import java.util.List;
291 import java.util.Map;
292 import java.util.concurrent.CountDownLatch;
293 import java.util.function.Consumer;
294 
295 
296 @SmallTest
297 @RunWith(AndroidTestingRunner.class)
298 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
299 @RunWithLooper
300 public class NotificationManagerServiceTest extends UiServiceTestCase {
301     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
302     private static final String TEST_PACKAGE = "The.name.is.Package.Test.Package";
303     private static final String PKG_NO_CHANNELS = "com.example.no.channels";
304     private static final int TEST_TASK_ID = 1;
305     private static final int UID_HEADLESS = 1_000_000;
306     private static final int TOAST_DURATION = 2_000;
307     private static final int SECONDARY_DISPLAY_ID = 42;
308 
309     private final int mUid = Binder.getCallingUid();
310     private final @UserIdInt int mUserId = UserHandle.getUserId(mUid);
311 
312     private TestableNotificationManagerService mService;
313     private INotificationManager mBinderService;
314     private NotificationManagerInternal mInternalService;
315     private ShortcutHelper mShortcutHelper;
316     @Mock
317     private IPackageManager mPackageManager;
318     @Mock
319     private PackageManager mPackageManagerClient;
320     @Mock
321     private PackageManagerInternal mPackageManagerInternal;
322     @Mock
323     private PermissionPolicyInternal mPermissionPolicyInternal;
324     @Mock
325     private WindowManagerInternal mWindowManagerInternal;
326     @Mock
327     private PermissionHelper mPermissionHelper;
328     private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();
329     private final String PKG = mContext.getPackageName();
330     private TestableLooper mTestableLooper;
331     @Mock
332     private RankingHelper mRankingHelper;
333     @Mock private PreferencesHelper mPreferencesHelper;
334     AtomicFile mPolicyFile;
335     File mFile;
336     @Mock
337     private NotificationUsageStats mUsageStats;
338     @Mock
339     private UsageStatsManagerInternal mAppUsageStats;
340     @Mock
341     private AudioManager mAudioManager;
342     @Mock
343     private LauncherApps mLauncherApps;
344     @Mock
345     private ShortcutServiceInternal mShortcutServiceInternal;
346     @Mock
347     private UserManager mUserManager;
348     @Mock
349     ActivityManager mActivityManager;
350     @Mock
351     TelecomManager mTelecomManager;
352     @Mock
353     Resources mResources;
354     @Mock
355     RankingHandler mRankingHandler;
356     @Mock
357     ActivityManagerInternal mAmi;
358     @Mock
359     JobSchedulerInternal mJsi;
360     @Mock
361     private Looper mMainLooper;
362     @Mock
363     private NotificationManager mMockNm;
364     @Mock
365     private PermissionManager mPermissionManager;
366     @Mock
367     private DevicePolicyManagerInternal mDevicePolicyManager;
368     @Mock
369     private PowerManager mPowerManager;
370     private final ArrayList<WakeLock> mAcquiredWakeLocks = new ArrayList<>();
371     private final TestPostNotificationTrackerFactory mPostNotificationTrackerFactory =
372             new TestPostNotificationTrackerFactory();
373 
374     @Mock
375     IIntentSender pi1;
376 
377     private static final int MAX_POST_DELAY = 1000;
378 
379     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
380             TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
381 
382     private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
383 
384     private static final String VALID_CONVO_SHORTCUT_ID = "shortcut";
385     private static final String SEARCH_SELECTOR_PKG = "searchSelector";
386     @Mock
387     private NotificationListeners mListeners;
388     @Mock
389     private NotificationListenerFilter mNlf;
390     @Mock private NotificationAssistants mAssistants;
391     @Mock private ConditionProviders mConditionProviders;
392     private ManagedServices.ManagedServiceInfo mListener;
393     @Mock private ICompanionDeviceManager mCompanionMgr;
394     @Mock SnoozeHelper mSnoozeHelper;
395     @Mock GroupHelper mGroupHelper;
396     @Mock
397     IBinder mPermOwner;
398     @Mock
399     IActivityManager mAm;
400     @Mock
401     ActivityTaskManagerInternal mAtm;
402     @Mock
403     IUriGrantsManager mUgm;
404     @Mock
405     UriGrantsManagerInternal mUgmInternal;
406     @Mock
407     AppOpsManager mAppOpsManager;
408     private AppOpsManager.OnOpChangedListener mOnPermissionChangeListener;
409     @Mock
410     private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
411             mNotificationAssistantAccessGrantedCallback;
412     @Mock
413     UserManager mUm;
414     @Mock
415     UserManagerInternal mUmInternal;
416     @Mock
417     NotificationHistoryManager mHistoryManager;
418     @Mock
419     StatsManager mStatsManager;
420     @Mock
421     AlarmManager mAlarmManager;
422     @Mock
423     MultiRateLimiter mToastRateLimiter;
424     BroadcastReceiver mPackageIntentReceiver;
425     BroadcastReceiver mUserSwitchIntentReceiver;
426     NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
427     TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;
428 
429     TestableFlagResolver mTestFlagResolver = new TestableFlagResolver();
430 
431     private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
432             1 << 30);
433     @Mock
434     StatusBarManagerInternal mStatusBar;
435 
436     private NotificationManagerService.WorkerHandler mWorkerHandler;
437 
438     private class TestableToastCallback extends ITransientNotification.Stub {
439         @Override
show(IBinder windowToken)440         public void show(IBinder windowToken) {
441         }
442 
443         @Override
hide()444         public void hide() {
445         }
446     }
447 
448     private class TestPostNotificationTrackerFactory implements PostNotificationTrackerFactory {
449 
450         private final List<PostNotificationTracker> mCreatedTrackers = new ArrayList<>();
451 
452         @Override
newTracker(@ullable WakeLock optionalWakeLock)453         public PostNotificationTracker newTracker(@Nullable WakeLock optionalWakeLock) {
454             PostNotificationTracker tracker = PostNotificationTrackerFactory.super.newTracker(
455                     optionalWakeLock);
456             mCreatedTrackers.add(tracker);
457             return tracker;
458         }
459     }
460 
461     @Before
setUp()462     public void setUp() throws Exception {
463         // Shell permisssions will override permissions of our app, so add all necessary permissions
464         // for this test here:
465         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
466                 "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG",
467                 "android.permission.READ_DEVICE_CONFIG",
468                 "android.permission.READ_CONTACTS");
469 
470         MockitoAnnotations.initMocks(this);
471 
472         DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
473         when(deviceIdleInternal.getNotificationAllowlistDuration()).thenReturn(3000L);
474 
475         LocalServices.removeServiceForTest(UserManagerInternal.class);
476         LocalServices.addService(UserManagerInternal.class, mUmInternal);
477         LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
478         LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
479         LocalServices.removeServiceForTest(WindowManagerInternal.class);
480         LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
481         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
482         LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
483         LocalServices.removeServiceForTest(DeviceIdleInternal.class);
484         LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
485         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
486         LocalServices.addService(ActivityManagerInternal.class, mAmi);
487         LocalServices.removeServiceForTest(JobSchedulerInternal.class);
488         LocalServices.addService(JobSchedulerInternal.class, mJsi);
489         LocalServices.removeServiceForTest(PackageManagerInternal.class);
490         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
491         LocalServices.removeServiceForTest(PermissionPolicyInternal.class);
492         LocalServices.addService(PermissionPolicyInternal.class, mPermissionPolicyInternal);
493         mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
494         mContext.addMockSystemService(NotificationManager.class, mMockNm);
495 
496         doNothing().when(mContext).sendBroadcastAsUser(any(), any());
497         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
498 
499         setDpmAppOppsExemptFromDismissal(false);
500 
501         mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
502                 mNotificationInstanceIdSequence);
503 
504         // Use this testable looper.
505         mTestableLooper = TestableLooper.get(this);
506         // MockPackageManager - default returns ApplicationInfo with matching calling UID
507         mContext.setMockPackageManager(mPackageManagerClient);
508 
509         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt()))
510                 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
511                     Object[] args = invocation.getArguments();
512                     return getApplicationInfo((String) args[0], mUid);
513                 });
514         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
515                 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
516                     Object[] args = invocation.getArguments();
517                     return getApplicationInfo((String) args[0], mUid);
518                 });
519         when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
520         when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenAnswer(
521                 (Answer<Boolean>) invocation -> {
522                     Object[] args = invocation.getArguments();
523                     return (int) args[1] == mUid;
524                 });
525         final LightsManager mockLightsManager = mock(LightsManager.class);
526         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
527         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
528         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
529         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
530         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
531         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
532         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt()))
533                 .thenReturn(INVALID_TASK_ID);
534         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
535         when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});
536 
537         when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true);
538 
539         ActivityManager.AppTask task = mock(ActivityManager.AppTask.class);
540         List<ActivityManager.AppTask> taskList = new ArrayList<>();
541         ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo();
542         taskInfo.taskId = TEST_TASK_ID;
543         when(task.getTaskInfo()).thenReturn(taskInfo);
544         taskList.add(task);
545         when(mAtm.getAppTasks(anyString(), anyInt())).thenReturn(taskList);
546 
547         // write to a test file; the system file isn't readable from tests
548         mFile = new File(mContext.getCacheDir(), "test.xml");
549         mFile.createNewFile();
550         final String preupgradeXml = "<notification-policy></notification-policy>";
551         mPolicyFile = new AtomicFile(mFile);
552         FileOutputStream fos = mPolicyFile.startWrite();
553         fos.write(preupgradeXml.getBytes());
554         mPolicyFile.finishWrite(fos);
555 
556         // Setup managed services
557         when(mNlf.isTypeAllowed(anyInt())).thenReturn(true);
558         when(mNlf.isPackageAllowed(any())).thenReturn(true);
559         when(mNlf.isPackageAllowed(null)).thenReturn(true);
560         when(mListeners.getNotificationListenerFilter(any())).thenReturn(mNlf);
561         mListener = mListeners.new ManagedServiceInfo(
562                 null, new ComponentName(PKG, "test_class"),
563                 mUserId, true, null, 0, 123);
564         ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
565         ArraySet<ComponentName> components = new ArraySet<>();
566         components.add(defaultComponent);
567         when(mListeners.getDefaultComponents()).thenReturn(components);
568         when(mConditionProviders.getDefaultPackages())
569                 .thenReturn(new ArraySet<>(Arrays.asList("config")));
570         when(mAssistants.getDefaultComponents()).thenReturn(components);
571         when(mAssistants.queryPackageForServices(
572                 anyString(), anyInt(), anyInt())).thenReturn(components);
573         when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener);
574         ManagedServices.Config listenerConfig = new ManagedServices.Config();
575         listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
576         when(mListeners.getConfig()).thenReturn(listenerConfig);
577         ManagedServices.Config assistantConfig = new ManagedServices.Config();
578         assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
579         when(mAssistants.getConfig()).thenReturn(assistantConfig);
580         ManagedServices.Config dndConfig = new ManagedServices.Config();
581         dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
582         when(mConditionProviders.getConfig()).thenReturn(dndConfig);
583 
584         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
585 
586         // Use the real PowerManager to back up the mock w.r.t. creating WakeLocks.
587         // This is because 1) we need a mock to verify() calls and tracking the created WakeLocks,
588         // but 2) PowerManager and WakeLock perform their own checks (e.g. correct arguments, don't
589         // call release twice, etc) and we want the test to fail if such misuse happens, too.
590         PowerManager realPowerManager = mContext.getSystemService(PowerManager.class);
591         when(mPowerManager.newWakeLock(anyInt(), anyString())).then(
592                 (Answer<WakeLock>) invocation -> {
593                     WakeLock wl = realPowerManager.newWakeLock(invocation.getArgument(0),
594                             invocation.getArgument(1));
595                     mAcquiredWakeLocks.add(wl);
596                     return wl;
597                 });
598         mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
599         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
600                 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false);
601 
602         // apps allowed as convos
603         mService.setStringArrayResourceValue(PKG_O);
604 
605         TestableResources tr = mContext.getOrCreateTestableResources();
606         tr.addOverride(com.android.internal.R.string.config_defaultSearchSelectorPackageName,
607                 SEARCH_SELECTOR_PKG);
608 
609         doAnswer(invocation -> {
610             mOnPermissionChangeListener = invocation.getArgument(2);
611             return null;
612         }).when(mAppOpsManager).startWatchingMode(eq(AppOpsManager.OP_POST_NOTIFICATION), any(),
613                 any());
614         when(mUmInternal.isUserInitialized(anyInt())).thenReturn(true);
615 
616         mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper()));
617         mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient,
618                 mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr,
619                 mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm,
620                 mAppUsageStats, mDevicePolicyManager, mUgm, mUgmInternal,
621                 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
622                 mock(TelephonyManager.class),
623                 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
624                 mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager,
625                 mPowerManager, mPostNotificationTrackerFactory);
626         // Return first true for RoleObserver main-thread check
627         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
628         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
629         verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
630         mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
631         verify(mHistoryManager).onBootPhaseAppsCanStart();
632 
633         mService.setAudioManager(mAudioManager);
634 
635         mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext);
636         mService.setStrongAuthTracker(mStrongAuthTracker);
637 
638         mShortcutHelper = mService.getShortcutHelper();
639         mShortcutHelper.setLauncherApps(mLauncherApps);
640         mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
641         mShortcutHelper.setUserManager(mUserManager);
642 
643         // Capture PackageIntentReceiver
644         ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
645                 ArgumentCaptor.forClass(BroadcastReceiver.class);
646         ArgumentCaptor<IntentFilter> intentFilterCaptor =
647                 ArgumentCaptor.forClass(IntentFilter.class);
648 
649         verify(mContext, atLeastOnce()).registerReceiverAsUser(broadcastReceiverCaptor.capture(),
650                 any(), intentFilterCaptor.capture(), any(), any());
651         verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(),
652                 intentFilterCaptor.capture());
653         List<BroadcastReceiver> broadcastReceivers = broadcastReceiverCaptor.getAllValues();
654         List<IntentFilter> intentFilters = intentFilterCaptor.getAllValues();
655 
656         for (int i = 0; i < intentFilters.size(); i++) {
657             final IntentFilter filter = intentFilters.get(i);
658             if (filter.hasAction(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED)
659                     && filter.hasAction(Intent.ACTION_PACKAGES_UNSUSPENDED)
660                     && filter.hasAction(Intent.ACTION_PACKAGES_SUSPENDED)) {
661                 mPackageIntentReceiver = broadcastReceivers.get(i);
662             }
663             if (filter.hasAction(Intent.ACTION_USER_SWITCHED)) {
664                 mUserSwitchIntentReceiver = broadcastReceivers.get(i);
665             }
666         }
667         assertNotNull("package intent receiver should exist", mPackageIntentReceiver);
668         assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver);
669 
670         // Pretend the shortcut exists
671         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
672         ShortcutInfo info = mock(ShortcutInfo.class);
673         when(info.getPackage()).thenReturn(PKG);
674         when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID);
675         when(info.getUserId()).thenReturn(USER_SYSTEM);
676         when(info.isLongLived()).thenReturn(true);
677         when(info.isEnabled()).thenReturn(true);
678         shortcutInfos.add(info);
679         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
680         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
681                 anyString(), anyInt(), any())).thenReturn(true);
682         when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
683         mockIsUserVisible(DEFAULT_DISPLAY, true);
684         mockIsVisibleBackgroundUsersSupported(false);
685 
686         // Set the testable bubble extractor
687         RankingHelper rankingHelper = mService.getRankingHelper();
688         BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
689         extractor.setActivityManager(mActivityManager);
690 
691         // Tests call directly into the Binder.
692         mBinderService = mService.getBinderService();
693         mInternalService = mService.getInternalService();
694 
695         mBinderService.createNotificationChannels(
696                 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
697         mBinderService.createNotificationChannels(
698                 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
699         mBinderService.createNotificationChannels(
700                 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
701         assertNotNull(mBinderService.getNotificationChannel(
702                 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
703         clearInvocations(mRankingHandler);
704         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
705 
706         mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false);
707         mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false);
708 
709         var checker = mock(TestableNotificationManagerService.ComponentPermissionChecker.class);
710         mService.permissionChecker = checker;
711         when(checker.check(anyString(), anyInt(), anyInt(), anyBoolean()))
712                 .thenReturn(PackageManager.PERMISSION_DENIED);
713     }
714 
715     @After
assertNotificationRecordLoggerCallsValid()716     public void assertNotificationRecordLoggerCallsValid() {
717         waitForIdle(); // Finish async work, including all logging calls done by Runnables.
718         for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
719             if (call.wasLogged) {
720                 assertNotNull(call.event);
721                 if (call.event == NOTIFICATION_POSTED || call.event == NOTIFICATION_UPDATED) {
722                     assertThat(call.postDurationMillisLogged).isGreaterThan(0);
723                 } else {
724                     assertThat(call.postDurationMillisLogged).isNull();
725                 }
726             }
727         }
728         assertThat(mNotificationRecordLogger.getPendingLogs()).isEmpty();
729     }
730 
731     @After
assertAllTrackersFinishedOrCancelled()732     public void assertAllTrackersFinishedOrCancelled() {
733         waitForIdle(); // Finish async work.
734         // Verify that no trackers were left dangling.
735         for (PostNotificationTracker tracker : mPostNotificationTrackerFactory.mCreatedTrackers) {
736             assertThat(tracker.isOngoing()).isFalse();
737         }
738         mPostNotificationTrackerFactory.mCreatedTrackers.clear();
739     }
740 
741     @After
assertAllWakeLocksReleased()742     public void assertAllWakeLocksReleased() {
743         waitForIdle(); // Finish async work.
744         for (WakeLock wakeLock : mAcquiredWakeLocks) {
745             assertThat(wakeLock.isHeld()).isFalse();
746         }
747     }
748 
749     @After
tearDown()750     public void tearDown() throws Exception {
751         if (mFile != null) mFile.delete();
752         clearDeviceConfig();
753 
754         try {
755             mService.onDestroy();
756         } catch (IllegalStateException | IllegalArgumentException e) {
757             // can throw if a broadcast receiver was never registered
758         }
759 
760         InstrumentationRegistry.getInstrumentation()
761                 .getUiAutomation().dropShellPermissionIdentity();
762         // Remove scheduled messages that would be processed when the test is already done, and
763         // could cause issues, for example, messages that remove/cancel shown toasts (this causes
764         // problematic interactions with mocks when they're no longer working as expected).
765         mWorkerHandler.removeCallbacksAndMessages(null);
766     }
767 
simulatePackageSuspendBroadcast(boolean suspend, String pkg, int uid)768     private void simulatePackageSuspendBroadcast(boolean suspend, String pkg,
769             int uid) {
770         // mimics receive broadcast that package is (un)suspended
771         // but does not actually (un)suspend the package
772         final Bundle extras = new Bundle();
773         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
774                 new String[]{pkg});
775         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, new int[]{uid});
776 
777         final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED
778                 : Intent.ACTION_PACKAGES_UNSUSPENDED;
779         final Intent intent = new Intent(action);
780         intent.putExtras(extras);
781 
782         mPackageIntentReceiver.onReceive(getContext(), intent);
783     }
784 
simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids)785     private void simulatePackageDistractionBroadcast(int flag, String[] pkgs, int[] uids) {
786         // mimics receive broadcast that package is (un)distracting
787         // but does not actually register that info with packagemanager
788         final Bundle extras = new Bundle();
789         extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgs);
790         extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, flag);
791         extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uids);
792 
793         final Intent intent = new Intent(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED);
794         intent.putExtras(extras);
795 
796         mPackageIntentReceiver.onReceive(getContext(), intent);
797     }
798 
generateResetComponentValues()799     private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
800         ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
801         changed.put(true, new ArrayList<>());
802         changed.put(false, new ArrayList<>());
803         return changed;
804     }
getApplicationInfo(String pkg, int uid)805     private ApplicationInfo getApplicationInfo(String pkg, int uid) {
806         final ApplicationInfo applicationInfo = new ApplicationInfo();
807         applicationInfo.uid = uid;
808         switch (pkg) {
809             case PKG_N_MR1:
810                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
811                 break;
812             case PKG_O:
813                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
814                 break;
815             case PKG_P:
816                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
817                 break;
818             default:
819                 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
820                 break;
821         }
822         return applicationInfo;
823     }
824 
waitForIdle()825     public void waitForIdle() {
826         mTestableLooper.processAllMessages();
827     }
828 
setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled, int pkgPref, boolean channelEnabled)829     private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
830             int pkgPref, boolean channelEnabled) {
831         Settings.Secure.putInt(mContext.getContentResolver(),
832                 Settings.Secure.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
833         mService.mPreferencesHelper.updateBubblesEnabled();
834         assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled(
835                 mock(UserHandle.class)));
836         try {
837             mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
838         } catch (RemoteException e) {
839             e.printStackTrace();
840         }
841         mTestNotificationChannel.setAllowBubbles(channelEnabled);
842     }
843 
generateSbn(String pkg, int uid, long postTime, int userId)844     private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
845         Notification.Builder nb = new Notification.Builder(mContext, "a")
846                 .setContentTitle("foo")
847                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
848         StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
849                 "tag" + System.currentTimeMillis(), uid, 0,
850                 nb.build(), new UserHandle(userId), null, postTime);
851         return sbn;
852     }
853 
generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary)854     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
855             String groupKey, boolean isSummary) {
856         return generateNotificationRecord(channel, id, "tag" + System.currentTimeMillis(), groupKey,
857                 isSummary);
858     }
859 
generateNotificationRecord(NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)860     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
861             String tag, String groupKey, boolean isSummary) {
862         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
863                 .setContentTitle("foo")
864                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
865                 .setGroup(groupKey)
866                 .setGroupSummary(isSummary);
867         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
868                 tag, mUid, 0,
869                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
870         return new NotificationRecord(mContext, sbn, channel);
871     }
872 
generateNotificationRecord(NotificationChannel channel)873     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
874         return generateNotificationRecord(channel, null);
875     }
876 
generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender)877     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
878             Notification.TvExtender extender) {
879         if (channel == null) {
880             channel = mTestNotificationChannel;
881         }
882         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
883                 .setContentTitle("foo")
884                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
885                 .addAction(new Notification.Action.Builder(null, "test", null).build());
886         if (extender != null) {
887             nb.extend(extender);
888         }
889         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
890                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
891         return new NotificationRecord(mContext, sbn, channel);
892     }
893 
generateNotificationRecord(NotificationChannel channel, int userId)894     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
895         return generateNotificationRecord(channel, 1, userId);
896     }
897 
generateNotificationRecord(NotificationChannel channel, int id, int userId)898     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
899             int userId) {
900         if (channel == null) {
901             channel = mTestNotificationChannel;
902         }
903         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
904                 .setContentTitle("foo")
905                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
906         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
907                 nb.build(), new UserHandle(userId), null, 0);
908         return new NotificationRecord(mContext, sbn, channel);
909     }
910 
generateMessageBubbleNotifRecord(NotificationChannel channel, String tag)911     private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
912             String tag) {
913         return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
914     }
915 
generateMessageBubbleNotifRecord(boolean addMetadata, NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary)916     private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
917             NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
918         if (channel == null) {
919             channel = mTestNotificationChannel;
920         }
921         if (tag == null) {
922             tag = "tag";
923         }
924         Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
925         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
926                 tag, mUid, 0,
927                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
928         return new NotificationRecord(mContext, sbn, channel);
929     }
930 
getSignalExtractorSideEffects()931     private Map<String, Answer> getSignalExtractorSideEffects() {
932         Map<String, Answer> answers = new ArrayMap<>();
933 
934         answers.put("override group key", invocationOnMock -> {
935             ((NotificationRecord) invocationOnMock.getArguments()[0])
936                     .setOverrideGroupKey("bananas");
937             return null;
938         });
939         answers.put("override people", invocationOnMock -> {
940             ((NotificationRecord) invocationOnMock.getArguments()[0])
941                     .setPeopleOverride(new ArrayList<>());
942             return null;
943         });
944         answers.put("snooze criteria", invocationOnMock -> {
945             ((NotificationRecord) invocationOnMock.getArguments()[0])
946                     .setSnoozeCriteria(new ArrayList<>());
947             return null;
948         });
949         answers.put("notification channel", invocationOnMock -> {
950             ((NotificationRecord) invocationOnMock.getArguments()[0])
951                     .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
952             return null;
953         });
954         answers.put("badging", invocationOnMock -> {
955             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
956             r.setShowBadge(!r.canShowBadge());
957             return null;
958         });
959         answers.put("bubbles", invocationOnMock -> {
960             NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
961             r.setAllowBubble(!r.canBubble());
962             return null;
963         });
964         answers.put("package visibility", invocationOnMock -> {
965             ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
966                     Notification.VISIBILITY_SECRET);
967             return null;
968         });
969 
970         return answers;
971     }
972 
clearDeviceConfig()973     private void clearDeviceConfig() {
974         DeviceConfig.resetToDefaults(
975                 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
976     }
977 
setDefaultAssistantInDeviceConfig(String componentName)978     private void setDefaultAssistantInDeviceConfig(String componentName) {
979         DeviceConfig.setProperty(
980                 DeviceConfig.NAMESPACE_SYSTEMUI,
981                 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
982                 componentName,
983                 false);
984     }
985 
getMessageStyleNotifBuilder(boolean addBubbleMetadata, String groupKey, boolean isSummary)986     private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
987             String groupKey, boolean isSummary) {
988         // Give it a person
989         Person person = new Person.Builder()
990                 .setName("bubblebot")
991                 .build();
992         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
993         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
994                 new Intent().setPackage(mContext.getPackageName()),
995                 PendingIntent.FLAG_MUTABLE);
996         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
997         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
998                 inputIntent).addRemoteInput(remoteInput)
999                 .build();
1000         // Make it messaging style
1001         Notification.Builder nb = new Notification.Builder(mContext,
1002                 mTestNotificationChannel.getId())
1003                 .setContentTitle("foo")
1004                 .setStyle(new Notification.MessagingStyle(person)
1005                         .setConversationTitle("Bubble Chat")
1006                         .addMessage("Hello?",
1007                                 SystemClock.currentThreadTimeMillis() - 300000, person)
1008                         .addMessage("Is it me you're looking for?",
1009                                 SystemClock.currentThreadTimeMillis(), person)
1010                 )
1011                 .setActions(replyAction)
1012                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1013                 .setShortcutId(VALID_CONVO_SHORTCUT_ID)
1014                 .setGroupSummary(isSummary);
1015         if (groupKey != null) {
1016             nb.setGroup(groupKey);
1017         }
1018         if (addBubbleMetadata) {
1019             nb.setBubbleMetadata(getBubbleMetadata());
1020         }
1021         return nb;
1022     }
1023 
getBubbleMetadata()1024     private Notification.BubbleMetadata getBubbleMetadata() {
1025         PendingIntent pendingIntent = mock(PendingIntent.class);
1026         Intent intent = mock(Intent.class);
1027         when(pendingIntent.getIntent()).thenReturn(intent);
1028         when(pendingIntent.getTarget()).thenReturn(pi1);
1029 
1030         ActivityInfo info = new ActivityInfo();
1031         info.resizeMode = RESIZE_MODE_RESIZEABLE;
1032         when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
1033 
1034         return new Notification.BubbleMetadata.Builder(
1035                 pendingIntent,
1036                 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
1037                 .build();
1038     }
1039 
addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)1040     private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
1041             throws RemoteException {
1042 
1043         String groupKey = "BUBBLE_GROUP";
1044 
1045         // Notification that has bubble metadata
1046         NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
1047                 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
1048 
1049         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
1050                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
1051                 nrBubble.getSbn().getUserId());
1052         waitForIdle();
1053 
1054         // Make sure we are a bubble
1055         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
1056         assertEquals(1, notifsAfter.length);
1057         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
1058 
1059         // Notification without bubble metadata
1060         NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
1061                 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
1062 
1063         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
1064                 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
1065                 nrPlain.getSbn().getUserId());
1066         waitForIdle();
1067 
1068         notifsAfter = mBinderService.getActiveNotifications(PKG);
1069         assertEquals(2, notifsAfter.length);
1070 
1071         // Summary notification for both of those
1072         NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
1073                 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
1074 
1075         if (summaryAutoCancel) {
1076             nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
1077         }
1078         mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
1079                 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
1080                 nrSummary.getSbn().getUserId());
1081         waitForIdle();
1082 
1083         notifsAfter = mBinderService.getActiveNotifications(PKG);
1084         assertEquals(3, notifsAfter.length);
1085 
1086         return nrSummary;
1087     }
1088 
1089     @Test
testLimitTimeOutBroadcast()1090     public void testLimitTimeOutBroadcast() {
1091         NotificationChannel channel = new NotificationChannel("id", "name",
1092                 NotificationManager.IMPORTANCE_HIGH);
1093         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
1094                 .setContentTitle("foo")
1095                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1096                 .setTimeoutAfter(1);
1097 
1098         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
1099                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
1100         NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
1101 
1102         mService.scheduleTimeoutLocked(r);
1103         ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
1104         verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
1105         assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
1106                 captor.getValue().getIntent().getPackage());
1107     }
1108 
1109     @Test
testDefaultAssistant_overrideDefault()1110     public void testDefaultAssistant_overrideDefault() {
1111         final int userId = mContext.getUserId();
1112         final String testComponent = "package/class";
1113         final List<UserInfo> userInfos = new ArrayList<>();
1114         userInfos.add(new UserInfo(userId, "", 0));
1115         final ArraySet<ComponentName> validAssistants = new ArraySet<>();
1116         validAssistants.add(ComponentName.unflattenFromString(testComponent));
1117         when(mActivityManager.isLowRamDevice()).thenReturn(false);
1118         when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
1119                 .thenReturn(validAssistants);
1120         when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
1121         when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
1122 
1123         mService.setDefaultAssistantForUser(userId);
1124 
1125         verify(mAssistants).setPackageOrComponentEnabled(
1126                 eq(testComponent), eq(userId), eq(true), eq(true), eq(false));
1127     }
1128 
1129     @Test
testCreateNotificationChannels_SingleChannel()1130     public void testCreateNotificationChannels_SingleChannel() throws Exception {
1131         final NotificationChannel channel =
1132                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1133         mBinderService.createNotificationChannels(PKG,
1134                 new ParceledListSlice(Arrays.asList(channel)));
1135         final NotificationChannel createdChannel =
1136                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1137         assertTrue(createdChannel != null);
1138     }
1139 
1140     @Test
testCreateNotificationChannels_NullChannelThrowsException()1141     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
1142         try {
1143             mBinderService.createNotificationChannels(PKG,
1144                     new ParceledListSlice(Arrays.asList((Object[])null)));
1145             fail("Exception should be thrown immediately.");
1146         } catch (NullPointerException e) {
1147             // pass
1148         }
1149     }
1150 
1151     @Test
testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()1152     public void testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()
1153             throws Exception {
1154         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID);
1155         final NotificationChannel channel =
1156                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1157         mBinderService.createNotificationChannels(PKG_NO_CHANNELS,
1158                 new ParceledListSlice(Arrays.asList(channel)));
1159         verify(mWorkerHandler).post(eq(new NotificationManagerService
1160                 .ShowNotificationPermissionPromptRunnable(PKG_NO_CHANNELS,
1161                 mUserId, TEST_TASK_ID, mPermissionPolicyInternal)));
1162     }
1163 
1164     @Test
testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()1165     public void testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()
1166             throws Exception {
1167         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID);
1168         assertTrue(mBinderService.getNumNotificationChannelsForPackage(PKG, mUid, true) > 0);
1169 
1170         final NotificationChannel channel =
1171                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1172         mBinderService.createNotificationChannels(PKG,
1173                 new ParceledListSlice(Arrays.asList(channel)));
1174         verify(mWorkerHandler, never()).post(any(
1175                 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class));
1176     }
1177 
1178     @Test
testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()1179     public void testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()
1180             throws Exception {
1181         reset(mPermissionPolicyInternal);
1182         when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())).thenReturn(TEST_TASK_ID);
1183 
1184         final NotificationChannel channel =
1185                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1186         mBinderService.createNotificationChannels(PKG,
1187                 new ParceledListSlice(Arrays.asList(channel)));
1188 
1189         verify(mWorkerHandler, never()).post(any(
1190                 NotificationManagerService.ShowNotificationPermissionPromptRunnable.class));
1191     }
1192 
1193     @Test
testCreateNotificationChannels_TwoChannels()1194     public void testCreateNotificationChannels_TwoChannels() throws Exception {
1195         final NotificationChannel channel1 =
1196                 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
1197         final NotificationChannel channel2 =
1198                 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
1199         mBinderService.createNotificationChannels(PKG,
1200                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
1201         assertTrue(mBinderService.getNotificationChannel(
1202                 PKG, mContext.getUserId(), PKG, "id1") != null);
1203         assertTrue(mBinderService.getNotificationChannel(
1204                 PKG, mContext.getUserId(), PKG, "id2") != null);
1205     }
1206 
1207     @Test
testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()1208     public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
1209             throws Exception {
1210         final NotificationChannel channel =
1211                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1212         mBinderService.createNotificationChannels(PKG,
1213                 new ParceledListSlice(Arrays.asList(channel)));
1214 
1215         // Recreating the channel doesn't throw, but ignores importance.
1216         final NotificationChannel dupeChannel =
1217                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
1218         mBinderService.createNotificationChannels(PKG,
1219                 new ParceledListSlice(Arrays.asList(dupeChannel)));
1220         final NotificationChannel createdChannel =
1221                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1222         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
1223     }
1224 
1225     @Test
testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()1226     public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
1227             throws Exception {
1228         final NotificationChannel channel =
1229                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1230         mBinderService.createNotificationChannels(PKG,
1231                 new ParceledListSlice(Arrays.asList(channel)));
1232 
1233         // Recreating with a lower importance is allowed to modify the channel.
1234         final NotificationChannel dupeChannel =
1235                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
1236         mBinderService.createNotificationChannels(PKG,
1237                 new ParceledListSlice(Arrays.asList(dupeChannel)));
1238         final NotificationChannel createdChannel =
1239                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1240         assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
1241     }
1242 
1243     @Test
testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()1244     public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
1245             throws Exception {
1246         final NotificationChannel channel =
1247                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1248         mBinderService.createNotificationChannels(PKG,
1249                 new ParceledListSlice(Arrays.asList(channel)));
1250 
1251         // The user modifies importance directly, can no longer be changed by the app.
1252         final NotificationChannel updatedChannel =
1253                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
1254         mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
1255 
1256         // Recreating with a lower importance leaves channel unchanged.
1257         final NotificationChannel dupeChannel =
1258                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
1259         mBinderService.createNotificationChannels(PKG,
1260                 new ParceledListSlice(Arrays.asList(dupeChannel)));
1261         final NotificationChannel createdChannel =
1262                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1263         assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
1264     }
1265 
1266     @Test
testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()1267     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
1268             throws Exception {
1269         final NotificationChannel channel1 =
1270                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
1271         final NotificationChannel channel2 =
1272                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
1273         mBinderService.createNotificationChannels(PKG,
1274                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
1275         final NotificationChannel createdChannel =
1276                 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
1277         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
1278     }
1279 
1280     @Test
testBlockedNotifications_suspended()1281     public void testBlockedNotifications_suspended() throws Exception {
1282         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
1283 
1284         NotificationChannel channel = new NotificationChannel("id", "name",
1285                 IMPORTANCE_HIGH);
1286         NotificationRecord r = generateNotificationRecord(channel);
1287 
1288         // isBlocked is only used for user blocking, not app suspension
1289         assertFalse(mService.isRecordBlockedLocked(r));
1290     }
1291 
1292     @Test
testBlockedNotifications_blockedChannel()1293     public void testBlockedNotifications_blockedChannel() throws Exception {
1294         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1295 
1296         NotificationChannel channel = new NotificationChannel("id", "name",
1297                 NotificationManager.IMPORTANCE_NONE);
1298         NotificationRecord r = generateNotificationRecord(channel);
1299         assertTrue(mService.isRecordBlockedLocked(r));
1300 
1301         mBinderService.createNotificationChannels(
1302                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1303         final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1304         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1305                 "testBlockedNotifications_blockedChannel",
1306                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1307         waitForIdle();
1308         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1309     }
1310 
1311     @Test
testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()1312     public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
1313             throws Exception {
1314         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1315         when(mAmi.applyForegroundServiceNotification(
1316                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1317 
1318         NotificationChannel channel = new NotificationChannel("blocked", "name",
1319                 NotificationManager.IMPORTANCE_NONE);
1320         mBinderService.createNotificationChannels(
1321                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1322 
1323         final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1324         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1325         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1326                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1327         waitForIdle();
1328         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1329         assertEquals(IMPORTANCE_LOW,
1330                 mService.getNotificationRecord(sbn.getKey()).getImportance());
1331         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1332                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1333     }
1334 
1335     @Test
testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()1336     public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
1337             throws Exception {
1338         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1339         when(mAmi.applyForegroundServiceNotification(
1340                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1341 
1342         NotificationChannel channel =
1343                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
1344         mBinderService.createNotificationChannels(
1345                 PKG, new ParceledListSlice(Arrays.asList(channel)));
1346 
1347         NotificationChannel update =
1348                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1349         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1350         waitForIdle();
1351         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1352                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1353 
1354         StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
1355         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1356         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
1357                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1358         waitForIdle();
1359         // The first time a foreground service notification is shown, we allow the channel
1360         // to be updated to allow it to be seen.
1361         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1362         assertEquals(IMPORTANCE_LOW,
1363                 mService.getNotificationRecord(sbn.getKey()).getImportance());
1364         assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1365                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1366         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1367         waitForIdle();
1368 
1369         update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1370         update.setUserVisibleTaskShown(true);
1371         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1372         waitForIdle();
1373         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1374                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1375 
1376         sbn = generateNotificationRecord(channel).getSbn();
1377         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1378         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1379                 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
1380                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1381         waitForIdle();
1382         // The second time it is shown, we keep the user's preference.
1383         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1384         assertNull(mService.getNotificationRecord(sbn.getKey()));
1385         assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1386                 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
1387     }
1388 
1389     @Test
testBlockedNotifications_blockedChannelGroup()1390     public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1391         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1392         mService.setPreferencesHelper(mPreferencesHelper);
1393         when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1394                 thenReturn(true);
1395 
1396         NotificationChannel channel = new NotificationChannel("id", "name",
1397                 NotificationManager.IMPORTANCE_HIGH);
1398         channel.setGroup("something");
1399         NotificationRecord r = generateNotificationRecord(channel);
1400         assertTrue(mService.isRecordBlockedLocked(r));
1401     }
1402 
1403     @Test
testEnqueuedBlockedNotifications_blockedApp()1404     public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
1405         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1406         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1407 
1408         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1409         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1410                 "testEnqueuedBlockedNotifications_blockedApp",
1411                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1412         waitForIdle();
1413         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1414     }
1415 
1416     @Test
testEnqueuedBlockedNotifications_blockedAppForegroundService()1417     public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1418         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1419         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1420         when(mAmi.applyForegroundServiceNotification(
1421                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1422 
1423         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1424         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
1425         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1426                 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
1427                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1428         waitForIdle();
1429         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1430         assertNull(mService.getNotificationRecord(sbn.getKey()));
1431     }
1432 
1433     /**
1434      * Confirm an application with the SEND_CATEGORY_CAR_NOTIFICATIONS permission on automotive
1435      * devices can use car categories.
1436      */
1437     @Test
testEnqueuedRestrictedNotifications_hasPermission()1438     public void testEnqueuedRestrictedNotifications_hasPermission() throws Exception {
1439         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1440                 .thenReturn(true);
1441         // SEND_CATEGORY_CAR_NOTIFICATIONS is a system-level permission that this test cannot
1442         // obtain. Mocking out enforce permission call to ensure notifications can be created when
1443         // permitted.
1444         doNothing().when(mContext).enforceCallingPermission(
1445                 eq("android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"), anyString());
1446         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1447                 Notification.CATEGORY_CAR_WARNING,
1448                 Notification.CATEGORY_CAR_INFORMATION);
1449         int id = 0;
1450         for (String category: categories) {
1451             final StatusBarNotification sbn =
1452                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
1453             sbn.getNotification().category = category;
1454             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1455                     "testEnqueuedRestrictedNotifications_asSystem",
1456                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1457         }
1458         waitForIdle();
1459         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1460     }
1461 
1462 
1463     /**
1464      * Confirm restricted notification categories only apply to automotive.
1465      */
1466     @Test
testEnqueuedRestrictedNotifications_notAutomotive()1467     public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1468         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1469                 .thenReturn(false);
1470         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1471                 Notification.CATEGORY_CAR_WARNING,
1472                 Notification.CATEGORY_CAR_INFORMATION);
1473         int id = 0;
1474         for (String category: categories) {
1475             final StatusBarNotification sbn =
1476                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
1477             sbn.getNotification().category = category;
1478             mBinderService.enqueueNotificationWithTag(PKG, PKG,
1479                     "testEnqueuedRestrictedNotifications_notAutomotive",
1480                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
1481         }
1482         waitForIdle();
1483         assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1484     }
1485 
1486     /**
1487      * Confirm if an application tries to use the car categories on a automotive device without the
1488      * SEND_CATEGORY_CAR_NOTIFICATIONS permission that a security exception will be thrown.
1489      */
1490     @Test
testEnqueuedRestrictedNotifications_noPermission()1491     public void testEnqueuedRestrictedNotifications_noPermission() throws Exception {
1492         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1493                 .thenReturn(true);
1494         List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1495                 Notification.CATEGORY_CAR_WARNING,
1496                 Notification.CATEGORY_CAR_INFORMATION);
1497         for (String category: categories) {
1498             final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1499             sbn.getNotification().category = category;
1500             try {
1501                 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1502                         "testEnqueuedRestrictedNotifications_badUser",
1503                         sbn.getId(), sbn.getNotification(), sbn.getUserId());
1504                 fail("Calls from non system apps should not allow use of restricted categories");
1505             } catch (SecurityException e) {
1506                 // pass
1507             }
1508         }
1509         waitForIdle();
1510         assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1511     }
1512 
1513     @Test
testSetNotificationsEnabledForPackage_noChange()1514     public void testSetNotificationsEnabledForPackage_noChange() throws Exception {
1515         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
1516         mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, true);
1517 
1518         verify(mPermissionHelper, never()).setNotificationPermission(
1519                 anyString(), anyInt(), anyBoolean(), anyBoolean());
1520     }
1521 
1522     @Test
testSetNotificationsEnabledForPackage()1523     public void testSetNotificationsEnabledForPackage() throws Exception {
1524         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
1525         mBinderService.setNotificationsEnabledForPackage(mContext.getPackageName(), mUid, false);
1526 
1527         verify(mPermissionHelper).setNotificationPermission(
1528                 mContext.getPackageName(), mUserId, false, true);
1529 
1530         verify(mAppOpsManager, never()).setMode(anyInt(), anyInt(), anyString(), anyInt());
1531         List<NotificationChannelLoggerFake.CallRecord> calls = mLogger.getCalls();
1532         Assert.assertEquals(
1533                 NotificationChannelLogger.NotificationChannelEvent.APP_NOTIFICATIONS_BLOCKED,
1534                 calls.get(calls.size() -1).event);
1535     }
1536 
1537     @Test
testBlockedNotifications_blockedByAssistant()1538     public void testBlockedNotifications_blockedByAssistant() throws Exception {
1539         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1540         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
1541 
1542         NotificationChannel channel = new NotificationChannel("id", "name",
1543                 NotificationManager.IMPORTANCE_HIGH);
1544         NotificationRecord r = generateNotificationRecord(channel);
1545         mService.addEnqueuedNotification(r);
1546 
1547         Bundle bundle = new Bundle();
1548         bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
1549         Adjustment adjustment = new Adjustment(
1550                 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
1551         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
1552 
1553         NotificationManagerService.PostNotificationRunnable runnable =
1554                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
1555                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
1556         runnable.run();
1557         waitForIdle();
1558 
1559         verify(mUsageStats, never()).registerPostedByApp(any());
1560     }
1561 
1562     @Test
testBlockedNotifications_blockedByUser()1563     public void testBlockedNotifications_blockedByUser() throws Exception {
1564         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1565         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
1566 
1567         NotificationChannel channel = new NotificationChannel("id", "name",
1568                 NotificationManager.IMPORTANCE_HIGH);
1569         NotificationRecord r = generateNotificationRecord(channel);
1570         mService.addEnqueuedNotification(r);
1571 
1572         when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false);
1573 
1574         NotificationManagerService.PostNotificationRunnable runnable =
1575                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
1576                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
1577         runnable.run();
1578         waitForIdle();
1579 
1580         verify(mUsageStats).registerBlocked(any());
1581         verify(mUsageStats, never()).registerPostedByApp(any());
1582     }
1583 
1584     @Test
testEnqueueNotificationInternal_noChannel()1585     public void testEnqueueNotificationInternal_noChannel() throws Exception {
1586         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1587         NotificationRecord nr = generateNotificationRecord(
1588                 new NotificationChannel("did not create", "", IMPORTANCE_DEFAULT));
1589 
1590         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
1591                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
1592         waitForIdle();
1593 
1594         verify(mPermissionHelper).hasPermission(mUid);
1595         verify(mPermissionHelper, never()).hasPermission(Process.SYSTEM_UID);
1596 
1597         reset(mPermissionHelper);
1598         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
1599 
1600         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
1601                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
1602         waitForIdle();
1603 
1604         verify(mPermissionHelper).hasPermission(mUid);
1605         assertThat(mService.mChannelToastsSent).contains(mUid);
1606     }
1607 
1608     @Test
testEnqueueNotification_appBlocked()1609     public void testEnqueueNotification_appBlocked() throws Exception {
1610         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
1611 
1612         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1613                 "testEnqueueNotification_appBlocked", 0,
1614                 generateNotificationRecord(null).getNotification(), 0);
1615         waitForIdle();
1616         verify(mWorkerHandler, never()).post(
1617                 any(NotificationManagerService.EnqueueNotificationRunnable.class));
1618     }
1619 
1620     @Test
testEnqueueNotificationWithTag_PopulatesGetActiveNotifications()1621     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
1622         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1623                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1624                 generateNotificationRecord(null).getNotification(), 0);
1625         waitForIdle();
1626         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
1627         assertEquals(1, notifs.length);
1628         assertEquals(1, mService.getNotificationRecordCount());
1629     }
1630 
1631     @Test
testEnqueueNotificationWithTag_WritesExpectedLogs()1632     public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
1633         final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1634         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1635                 generateNotificationRecord(null).getNotification(), 0);
1636         waitForIdle();
1637         assertEquals(1, mNotificationRecordLogger.numCalls());
1638 
1639         NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
1640         assertTrue(call.wasLogged);
1641         assertEquals(NOTIFICATION_POSTED, call.event);
1642         assertNotNull(call.r);
1643         assertNull(call.old);
1644         assertEquals(0, call.position);
1645         assertEquals(0, call.buzzBeepBlink);
1646         assertEquals(PKG, call.r.getSbn().getPackageName());
1647         assertEquals(0, call.r.getSbn().getId());
1648         assertEquals(tag, call.r.getSbn().getTag());
1649         assertEquals(1, call.getInstanceId());  // Fake instance IDs are assigned in order
1650         assertThat(call.postDurationMillisLogged).isGreaterThan(0);
1651     }
1652 
1653     @Test
testEnqueueNotificationWithTag_LogsOnMajorUpdates()1654     public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1655         final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1656         Notification original = new Notification.Builder(mContext,
1657                 mTestNotificationChannel.getId())
1658                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1659         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1660         Notification update = new Notification.Builder(mContext,
1661                 mTestNotificationChannel.getId())
1662                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1663                 .setCategory(Notification.CATEGORY_ALARM).build();
1664         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1665         waitForIdle();
1666         assertEquals(2, mNotificationRecordLogger.numCalls());
1667 
1668         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1669         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1670         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
1671         assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0);
1672 
1673         assertTrue(mNotificationRecordLogger.get(1).wasLogged);
1674         assertEquals(NOTIFICATION_UPDATED, mNotificationRecordLogger.event(1));
1675         // Instance ID doesn't change on update of an active notification
1676         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
1677         assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isGreaterThan(0);
1678     }
1679 
1680     @Test
testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate()1681     public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1682         final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
1683         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1684                 generateNotificationRecord(null).getNotification(), 0);
1685         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1686                 generateNotificationRecord(null).getNotification(), 0);
1687         waitForIdle();
1688         assertEquals(2, mNotificationRecordLogger.numCalls());
1689         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1690         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1691         assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1692         assertNull(mNotificationRecordLogger.event(1));
1693     }
1694 
1695     @Test
testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate()1696     public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1697         final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1698         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1699                 generateNotificationRecord(null).getNotification(),
1700                 0);
1701         final Notification notif = generateNotificationRecord(null).getNotification();
1702         notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1703         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1704         waitForIdle();
1705         assertEquals(2, mNotificationRecordLogger.numCalls());
1706         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1707         assertNull(mNotificationRecordLogger.event(1));
1708     }
1709 
1710     @Test
testEnqueueNotificationWithTag_LogsAgainAfterCancel()1711     public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1712         final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1713         Notification notification = new Notification.Builder(mContext,
1714                 mTestNotificationChannel.getId())
1715                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1716         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1717         waitForIdle();
1718         mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1719         waitForIdle();
1720         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1721         waitForIdle();
1722         assertEquals(3, mNotificationRecordLogger.numCalls());
1723 
1724         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(0));
1725         assertTrue(mNotificationRecordLogger.get(0).wasLogged);
1726         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
1727         assertThat(mNotificationRecordLogger.get(0).postDurationMillisLogged).isGreaterThan(0);
1728 
1729         assertEquals(
1730                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
1731                 mNotificationRecordLogger.event(1));
1732         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
1733         // Cancel is not post, so no logged post_duration_millis.
1734         assertThat(mNotificationRecordLogger.get(1).postDurationMillisLogged).isNull();
1735 
1736         assertEquals(NOTIFICATION_POSTED, mNotificationRecordLogger.event(2));
1737         assertTrue(mNotificationRecordLogger.get(2).wasLogged);
1738         // New instance ID because notification was canceled before re-post
1739         assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
1740         assertThat(mNotificationRecordLogger.get(2).postDurationMillisLogged).isGreaterThan(0);
1741     }
1742 
1743     @Test
testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed()1744     public void testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed() throws Exception {
1745         when(mAmi.applyForegroundServiceNotification(
1746                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
1747         mContext.getTestablePermissions().setPermission(
1748                 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED);
1749 
1750         final String tag = "testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed";
1751 
1752         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1753                 .setContentTitle("foo")
1754                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1755                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
1756                 .build();
1757         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, tag, mUid, 0,
1758                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
1759         mBinderService.enqueueNotificationWithTag(PKG, PKG, tag,
1760                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1761         waitForIdle();
1762 
1763         StatusBarNotification[] notifs =
1764                 mBinderService.getActiveNotifications(PKG);
1765         assertThat(notifs[0].getNotification().flags).isEqualTo(
1766                 FLAG_FOREGROUND_SERVICE | FLAG_CAN_COLORIZE | FLAG_NO_CLEAR);
1767     }
1768 
1769     @Test
testEnqueueNotificationWithTag_nullAction_fixed()1770     public void testEnqueueNotificationWithTag_nullAction_fixed() throws Exception {
1771         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1772                 .setContentTitle("foo")
1773                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1774                 .addAction(new Notification.Action.Builder(null, "one", null).build())
1775                 .addAction(new Notification.Action.Builder(null, "two", null).build())
1776                 .addAction(new Notification.Action.Builder(null, "three", null).build())
1777                 .build();
1778         n.actions[1] = null;
1779 
1780         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0);
1781         waitForIdle();
1782 
1783         StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG);
1784         assertThat(posted).hasLength(1);
1785         assertThat(posted[0].getNotification().actions).hasLength(2);
1786         assertThat(posted[0].getNotification().actions[0].title.toString()).isEqualTo("one");
1787         assertThat(posted[0].getNotification().actions[1].title.toString()).isEqualTo("three");
1788     }
1789 
1790     @Test
testEnqueueNotificationWithTag_allNullActions_fixed()1791     public void testEnqueueNotificationWithTag_allNullActions_fixed() throws Exception {
1792         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1793                 .setContentTitle("foo")
1794                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1795                 .addAction(new Notification.Action.Builder(null, "one", null).build())
1796                 .addAction(new Notification.Action.Builder(null, "two", null).build())
1797                 .build();
1798         n.actions[0] = null;
1799         n.actions[1] = null;
1800 
1801         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0);
1802         waitForIdle();
1803 
1804         StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG);
1805         assertThat(posted).hasLength(1);
1806         assertThat(posted[0].getNotification().actions).isNull();
1807     }
1808 
1809     @Test
enqueueNotificationWithTag_usesAndFinishesTracker()1810     public void enqueueNotificationWithTag_usesAndFinishesTracker() throws Exception {
1811         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1812                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1813                 generateNotificationRecord(null).getNotification(), 0);
1814 
1815         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1816         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isTrue();
1817 
1818         waitForIdle();
1819 
1820         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(1);
1821         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1822         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1823     }
1824 
1825     @Test
enqueueNotificationWithTag_throws_usesAndCancelsTracker()1826     public void enqueueNotificationWithTag_throws_usesAndCancelsTracker() throws Exception {
1827         // Simulate not enqueued due to rejected inputs.
1828         assertThrows(Exception.class,
1829                 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG,
1830                         "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1831                         /* notification= */ null, 0));
1832 
1833         waitForIdle();
1834 
1835         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0);
1836         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1837         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1838     }
1839 
1840     @Test
enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker()1841     public void enqueueNotificationWithTag_notEnqueued_usesAndCancelsTracker() throws Exception {
1842         // Simulate not enqueued due to snoozing inputs.
1843         when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any()))
1844                 .thenReturn("zzzzzzz");
1845 
1846         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1847                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1848                 generateNotificationRecord(null).getNotification(), 0);
1849         waitForIdle();
1850 
1851         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0);
1852         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1853         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1854     }
1855 
1856     @Test
enqueueNotificationWithTag_notPosted_usesAndCancelsTracker()1857     public void enqueueNotificationWithTag_notPosted_usesAndCancelsTracker() throws Exception {
1858         // Simulate not posted due to blocked app.
1859         when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false);
1860 
1861         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1862                 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
1863                 generateNotificationRecord(null).getNotification(), 0);
1864         waitForIdle();
1865 
1866         assertThat(mBinderService.getActiveNotifications(PKG)).hasLength(0);
1867         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers).hasSize(1);
1868         assertThat(mPostNotificationTrackerFactory.mCreatedTrackers.get(0).isOngoing()).isFalse();
1869     }
1870 
1871     @Test
enqueueNotification_acquiresAndReleasesWakeLock()1872     public void enqueueNotification_acquiresAndReleasesWakeLock() throws Exception {
1873         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1874                 "enqueueNotification_acquiresAndReleasesWakeLock", 0,
1875                 generateNotificationRecord(null).getNotification(), 0);
1876 
1877         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1878         assertThat(mAcquiredWakeLocks).hasSize(1);
1879         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
1880 
1881         waitForIdle();
1882 
1883         assertThat(mAcquiredWakeLocks).hasSize(1);
1884         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1885     }
1886 
1887     @Test
enqueueNotification_throws_acquiresAndReleasesWakeLock()1888     public void enqueueNotification_throws_acquiresAndReleasesWakeLock() throws Exception {
1889         // Simulate not enqueued due to rejected inputs.
1890         assertThrows(Exception.class,
1891                 () -> mBinderService.enqueueNotificationWithTag(PKG, PKG,
1892                         "enqueueNotification_throws_acquiresAndReleasesWakeLock", 0,
1893                         /* notification= */ null, 0));
1894 
1895         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1896         assertThat(mAcquiredWakeLocks).hasSize(1);
1897         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1898     }
1899 
1900     @Test
enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock()1901     public void enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock() throws Exception {
1902         // Simulate not enqueued due to snoozing inputs.
1903         when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any()))
1904                 .thenReturn("zzzzzzz");
1905 
1906         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1907                 "enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock", 0,
1908                 generateNotificationRecord(null).getNotification(), 0);
1909 
1910         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1911         assertThat(mAcquiredWakeLocks).hasSize(1);
1912         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
1913 
1914         waitForIdle();
1915 
1916         assertThat(mAcquiredWakeLocks).hasSize(1);
1917         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1918     }
1919 
1920     @Test
enqueueNotification_notPosted_acquiresAndReleasesWakeLock()1921     public void enqueueNotification_notPosted_acquiresAndReleasesWakeLock() throws Exception {
1922         // Simulate enqueued but not posted due to missing small icon.
1923         Notification notif = new Notification.Builder(mContext, mTestNotificationChannel.getId())
1924                 .setContentTitle("foo")
1925                 .build();
1926 
1927         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1928                 "enqueueNotification_notPosted_acquiresAndReleasesWakeLock", 0,
1929                 notif, 0);
1930 
1931         verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1932         assertThat(mAcquiredWakeLocks).hasSize(1);
1933         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
1934 
1935         waitForIdle();
1936 
1937         // NLSes were not called.
1938         verify(mListeners, never()).prepareNotifyPostedLocked(any(), any(), anyBoolean());
1939 
1940         assertThat(mAcquiredWakeLocks).hasSize(1);
1941         assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
1942     }
1943 
1944     @Test
enqueueNotification_setsWakeLockWorkSource()1945     public void enqueueNotification_setsWakeLockWorkSource() throws Exception {
1946         // Use a "full" mock for the PowerManager (instead of the one that delegates to the real
1947         // service) so we can return a mocked WakeLock that we can verify() on.
1948         reset(mPowerManager);
1949         WakeLock wakeLock = mock(WakeLock.class);
1950         when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(wakeLock);
1951 
1952         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1953                 "enqueueNotification_setsWakeLockWorkSource", 0,
1954                 generateNotificationRecord(null).getNotification(), 0);
1955         waitForIdle();
1956 
1957         InOrder inOrder = inOrder(mPowerManager, wakeLock);
1958         inOrder.verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
1959         inOrder.verify(wakeLock).setWorkSource(eq(new WorkSource(mUid, PKG)));
1960         inOrder.verify(wakeLock).acquire(anyLong());
1961         inOrder.verify(wakeLock).release();
1962         inOrder.verifyNoMoreInteractions();
1963     }
1964 
1965     @Test
enqueueNotification_wakeLockSystemPropertyOff_noWakeLock()1966     public void enqueueNotification_wakeLockSystemPropertyOff_noWakeLock() throws Exception {
1967         mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, false);
1968         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
1969                 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false);
1970 
1971         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1972                 "enqueueNotification_setsWakeLockWorkSource", 0,
1973                 generateNotificationRecord(null).getNotification(), 0);
1974         waitForIdle();
1975 
1976         verifyZeroInteractions(mPowerManager);
1977     }
1978 
1979     @Test
enqueueNotification_wakeLockDeviceConfigOff_noWakeLock()1980     public void enqueueNotification_wakeLockDeviceConfigOff_noWakeLock() throws Exception {
1981         mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
1982         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
1983                 SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "false", false);
1984 
1985         mBinderService.enqueueNotificationWithTag(PKG, PKG,
1986                 "enqueueNotification_setsWakeLockWorkSource", 0,
1987                 generateNotificationRecord(null).getNotification(), 0);
1988         waitForIdle();
1989 
1990         verifyZeroInteractions(mPowerManager);
1991     }
1992 
1993     @Test
testCancelNonexistentNotification()1994     public void testCancelNonexistentNotification() throws Exception {
1995         mBinderService.cancelNotificationWithTag(PKG, PKG,
1996                 "testCancelNonexistentNotification", 0, 0);
1997         waitForIdle();
1998         // The notification record logger doesn't even get called when a nonexistent notification
1999         // is cancelled, because that happens very frequently and is not interesting.
2000         assertEquals(0, mNotificationRecordLogger.numCalls());
2001     }
2002 
2003     @Test
testCancelNotificationImmediatelyAfterEnqueue()2004     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
2005         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2006                 "testCancelNotificationImmediatelyAfterEnqueue", 0,
2007                 generateNotificationRecord(null).getNotification(), 0);
2008         mBinderService.cancelNotificationWithTag(PKG, PKG,
2009                 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
2010         waitForIdle();
2011         StatusBarNotification[] notifs =
2012                 mBinderService.getActiveNotifications(PKG);
2013         assertEquals(0, notifs.length);
2014         assertEquals(0, mService.getNotificationRecordCount());
2015     }
2016 
2017     @Test
testPostCancelPostNotifiesListeners()2018     public void testPostCancelPostNotifiesListeners() throws Exception {
2019         // WHEN a notification is posted
2020         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2021         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
2022                 sbn.getNotification(), sbn.getUserId());
2023         mTestableLooper.moveTimeForward(1);
2024         // THEN it is canceled
2025         mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
2026         mTestableLooper.moveTimeForward(1);
2027         // THEN it is posted again (before the cancel has a chance to finish)
2028         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
2029                 sbn.getNotification(), sbn.getUserId());
2030         // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
2031         waitForIdle();
2032 
2033         // The final enqueue made it to the listener instead of being canceled
2034         StatusBarNotification[] notifs =
2035                 mBinderService.getActiveNotifications(PKG);
2036         assertEquals(1, notifs.length);
2037         assertEquals(1, mService.getNotificationRecordCount());
2038     }
2039 
2040     @Test
testCancelNotificationWhilePostedAndEnqueued()2041     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
2042         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2043                 "testCancelNotificationWhilePostedAndEnqueued", 0,
2044                 generateNotificationRecord(null).getNotification(), 0);
2045         waitForIdle();
2046         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2047                 "testCancelNotificationWhilePostedAndEnqueued", 0,
2048                 generateNotificationRecord(null).getNotification(), 0);
2049         mBinderService.cancelNotificationWithTag(PKG, PKG,
2050                 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
2051         waitForIdle();
2052         StatusBarNotification[] notifs =
2053                 mBinderService.getActiveNotifications(PKG);
2054         assertEquals(0, notifs.length);
2055         assertEquals(0, mService.getNotificationRecordCount());
2056         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
2057         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
2058         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
2059     }
2060 
2061     @Test
testCancelNotificationsFromListenerImmediatelyAfterEnqueue()2062     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
2063         NotificationRecord r = generateNotificationRecord(null);
2064         final StatusBarNotification sbn = r.getSbn();
2065         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2066                 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
2067                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2068         mBinderService.cancelNotificationsFromListener(null, null);
2069         waitForIdle();
2070         StatusBarNotification[] notifs =
2071                 mBinderService.getActiveNotifications(sbn.getPackageName());
2072         assertEquals(0, notifs.length);
2073         assertEquals(0, mService.getNotificationRecordCount());
2074     }
2075 
2076     @Test
testCancelAllNotificationsImmediatelyAfterEnqueue()2077     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
2078         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2079         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2080                 "testCancelAllNotificationsImmediatelyAfterEnqueue",
2081                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2082         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2083         waitForIdle();
2084         StatusBarNotification[] notifs =
2085                 mBinderService.getActiveNotifications(sbn.getPackageName());
2086         assertEquals(0, notifs.length);
2087         assertEquals(0, mService.getNotificationRecordCount());
2088     }
2089 
2090     @Test
testUserInitiatedClearAll_noLeak()2091     public void testUserInitiatedClearAll_noLeak() throws Exception {
2092         final NotificationRecord n = generateNotificationRecord(
2093                 mTestNotificationChannel, 1, "group", true);
2094 
2095         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2096                 "testUserInitiatedClearAll_noLeak",
2097                 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
2098         waitForIdle();
2099 
2100         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2101                 n.getUserId());
2102         waitForIdle();
2103         StatusBarNotification[] notifs =
2104                 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
2105         assertEquals(0, notifs.length);
2106         assertEquals(0, mService.getNotificationRecordCount());
2107         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
2108         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
2109         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
2110     }
2111 
2112     @Test
testCancelAllNotificationsCancelsChildren()2113     public void testCancelAllNotificationsCancelsChildren() throws Exception {
2114         final NotificationRecord parent = generateNotificationRecord(
2115                 mTestNotificationChannel, 1, "group1", true);
2116         final NotificationRecord child = generateNotificationRecord(
2117                 mTestNotificationChannel, 2, "group1", false);
2118 
2119         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2120                 "testCancelAllNotificationsCancelsChildren",
2121                 parent.getSbn().getId(), parent.getSbn().getNotification(),
2122                 parent.getSbn().getUserId());
2123         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2124                 "testCancelAllNotificationsCancelsChildren",
2125                 child.getSbn().getId(), child.getSbn().getNotification(),
2126                 child.getSbn().getUserId());
2127         waitForIdle();
2128 
2129         mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
2130         waitForIdle();
2131         assertEquals(0, mService.getNotificationRecordCount());
2132     }
2133 
2134     @Test
testCancelAllNotificationsMultipleEnqueuedDoesNotCrash()2135     public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
2136         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2137         for (int i = 0; i < 10; i++) {
2138             mBinderService.enqueueNotificationWithTag(PKG, PKG,
2139                     "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
2140                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
2141         }
2142         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2143         waitForIdle();
2144 
2145         assertEquals(0, mService.getNotificationRecordCount());
2146     }
2147 
2148     @Test
testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash()2149     public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
2150         final NotificationRecord parent = generateNotificationRecord(
2151                 mTestNotificationChannel, 1, "group1", true);
2152         final NotificationRecord parentAsChild = generateNotificationRecord(
2153                 mTestNotificationChannel, 1, "group1", false);
2154         final NotificationRecord child = generateNotificationRecord(
2155                 mTestNotificationChannel, 2, "group1", false);
2156 
2157         // fully post parent notification
2158         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2159                 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
2160                 parent.getSbn().getId(), parent.getSbn().getNotification(),
2161                 parent.getSbn().getUserId());
2162         waitForIdle();
2163 
2164         // enqueue the child several times
2165         for (int i = 0; i < 10; i++) {
2166             mBinderService.enqueueNotificationWithTag(PKG, PKG,
2167                     "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
2168                     child.getSbn().getId(), child.getSbn().getNotification(),
2169                     child.getSbn().getUserId());
2170         }
2171         // make the parent a child, which will cancel the child notification
2172         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2173                 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
2174                 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
2175                 parentAsChild.getSbn().getUserId());
2176         waitForIdle();
2177 
2178         assertEquals(0, mService.getNotificationRecordCount());
2179     }
2180 
2181     @Test
testAutobundledSummary_notificationAdded()2182     public void testAutobundledSummary_notificationAdded() {
2183         NotificationRecord summary =
2184                 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
2185         summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
2186         mService.addNotification(summary);
2187         mService.mSummaryByGroupKey.put("pkg", summary);
2188         mService.mAutobundledSummaries.put(0, new ArrayMap<>());
2189         mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
2190 
2191         mService.updateAutobundledSummaryFlags(
2192                 0, "pkg", GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT, false);
2193         waitForIdle();
2194 
2195         assertTrue(summary.getSbn().isOngoing());
2196     }
2197 
2198     @Test
testAutobundledSummary_notificationRemoved()2199     public void testAutobundledSummary_notificationRemoved() {
2200         NotificationRecord summary =
2201                 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
2202         summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
2203         summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2204         mService.addNotification(summary);
2205         mService.mAutobundledSummaries.put(0, new ArrayMap<>());
2206         mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
2207         mService.mSummaryByGroupKey.put("pkg", summary);
2208 
2209         mService.updateAutobundledSummaryFlags(0, "pkg", GroupHelper.BASE_FLAGS, false);
2210         waitForIdle();
2211 
2212         assertFalse(summary.getSbn().isOngoing());
2213     }
2214 
2215     @Test
testCancelAllNotifications_IgnoreForegroundService()2216     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
2217         when(mAmi.applyForegroundServiceNotification(
2218                 any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
2219         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2220         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2221         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2222                 "testCancelAllNotifications_IgnoreForegroundService",
2223                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2224         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2225         waitForIdle();
2226         StatusBarNotification[] notifs =
2227                 mBinderService.getActiveNotifications(sbn.getPackageName());
2228         assertEquals(1, notifs.length);
2229         assertEquals(1, mService.getNotificationRecordCount());
2230     }
2231 
2232     @Test
testCancelAllNotifications_FgsFlag_NoFgs_Allowed()2233     public void testCancelAllNotifications_FgsFlag_NoFgs_Allowed() throws Exception {
2234         when(mAmi.applyForegroundServiceNotification(
2235                 any(), anyString(), anyInt(), anyString(), anyInt()))
2236                 .thenReturn(NOT_FOREGROUND_SERVICE);
2237         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2238         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2239         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2240                 "testCancelAllNotifications_IgnoreForegroundService",
2241                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2242         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2243         waitForIdle();
2244         StatusBarNotification[] notifs =
2245                 mBinderService.getActiveNotifications(sbn.getPackageName());
2246         assertEquals(0, notifs.length);
2247     }
2248 
2249     @Test
testCancelAllNotifications_IgnoreOtherPackages()2250     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
2251         when(mAmi.applyForegroundServiceNotification(
2252                 any(), anyString(), anyInt(), anyString(), anyInt()))
2253                 .thenReturn(SHOW_IMMEDIATELY);
2254         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2255         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2256         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2257                 "testCancelAllNotifications_IgnoreOtherPackages",
2258                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2259         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
2260         waitForIdle();
2261         StatusBarNotification[] notifs =
2262                 mBinderService.getActiveNotifications(sbn.getPackageName());
2263         assertEquals(1, notifs.length);
2264         assertEquals(1, mService.getNotificationRecordCount());
2265     }
2266 
2267     @Test
testCancelAllNotifications_NullPkgRemovesAll()2268     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
2269         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2270         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2271                 "testCancelAllNotifications_NullPkgRemovesAll",
2272                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2273         mBinderService.cancelAllNotifications(null, sbn.getUserId());
2274         waitForIdle();
2275         StatusBarNotification[] notifs =
2276                 mBinderService.getActiveNotifications(sbn.getPackageName());
2277         assertEquals(0, notifs.length);
2278         assertEquals(0, mService.getNotificationRecordCount());
2279     }
2280 
2281     @Test
testCancelAllNotifications_NullPkgIgnoresUserAllNotifications()2282     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
2283         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2284         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2285                 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
2286                 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
2287         // Null pkg is how we signal a user switch.
2288         mBinderService.cancelAllNotifications(null, sbn.getUserId());
2289         waitForIdle();
2290         StatusBarNotification[] notifs =
2291                 mBinderService.getActiveNotifications(sbn.getPackageName());
2292         assertEquals(1, notifs.length);
2293         assertEquals(1, mService.getNotificationRecordCount());
2294     }
2295 
2296     @Test
testAppInitiatedCancelAllNotifications_CancelsNoClearFlag()2297     public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
2298         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2299         sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2300         mBinderService.enqueueNotificationWithTag(PKG, PKG,
2301                 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
2302                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2303         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2304         waitForIdle();
2305         StatusBarNotification[] notifs =
2306                 mBinderService.getActiveNotifications(sbn.getPackageName());
2307         assertEquals(0, notifs.length);
2308     }
2309 
2310     @Test
testCancelAllNotifications_CancelsNoClearFlag()2311     public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
2312         final NotificationRecord notif = generateNotificationRecord(
2313                 mTestNotificationChannel, 1, "group", true);
2314         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2315         mService.addNotification(notif);
2316         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0,
2317                 notif.getUserId(), REASON_CANCEL);
2318         waitForIdle();
2319         StatusBarNotification[] notifs =
2320                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2321         assertEquals(0, notifs.length);
2322     }
2323 
2324     @Test
testUserInitiatedCancelAllOnClearAll_NoClearFlag()2325     public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
2326         final NotificationRecord notif = generateNotificationRecord(
2327                 mTestNotificationChannel, 1, "group", true);
2328         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2329         mService.addNotification(notif);
2330 
2331         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2332                 notif.getUserId());
2333         waitForIdle();
2334         StatusBarNotification[] notifs =
2335                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
2336         assertEquals(1, notifs.length);
2337     }
2338 
2339     @Test
testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue()2340     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
2341         when(mAmi.applyForegroundServiceNotification(
2342                 any(), anyString(), anyInt(), anyString(), anyInt()))
2343                 .thenReturn(SHOW_IMMEDIATELY);
2344         Notification n =
2345                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2346                         .setSmallIcon(android.R.drawable.sym_def_app_icon)
2347                         .build();
2348         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
2349                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
2350         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2351         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2352                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2353         mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
2354                 sbn.getUserId());
2355         waitForIdle();
2356         StatusBarNotification[] notifs =
2357                 mBinderService.getActiveNotifications(sbn.getPackageName());
2358         assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
2359     }
2360 
2361     @Test
testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag()2362     public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
2363         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
2364         sbn.getNotification().flags =
2365                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
2366         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
2367                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2368         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
2369         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
2370                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2371         mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
2372                 sbn.getUserId());
2373         waitForIdle();
2374         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
2375         assertEquals(0, mService.getNotificationRecordCount());
2376     }
2377 
2378     @Test
testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()2379     public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()
2380             throws Exception {
2381         when(mAmi.applyForegroundServiceNotification(
2382                 any(), anyString(), anyInt(), anyString(), anyInt()))
2383                 .thenReturn(SHOW_IMMEDIATELY);
2384         mService.isSystemUid = false;
2385         mService.isSystemAppId = false;
2386         final NotificationRecord parent = generateNotificationRecord(
2387                 mTestNotificationChannel, 1, "group", true);
2388         final NotificationRecord child = generateNotificationRecord(
2389                 mTestNotificationChannel, 2, "group", false);
2390         final NotificationRecord child2 = generateNotificationRecord(
2391                 mTestNotificationChannel, 3, "group", false);
2392         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2393         mService.addNotification(parent);
2394         mService.addNotification(child);
2395         mService.addNotification(child2);
2396         mService.getBinderService().cancelNotificationWithTag(
2397                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2398                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2399         waitForIdle();
2400         StatusBarNotification[] notifs =
2401                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2402         assertEquals(1, notifs.length);
2403     }
2404 
2405     @Test
testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()2406     public void testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()
2407             throws Exception {
2408         when(mAmi.applyForegroundServiceNotification(
2409                 any(), anyString(), anyInt(), anyString(), anyInt()))
2410                 .thenReturn(SHOW_IMMEDIATELY);
2411         mService.isSystemUid = false;
2412         mService.isSystemAppId = false;
2413         final NotificationRecord parent = generateNotificationRecord(
2414                 mTestNotificationChannel, 1, "group", true);
2415         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2416         final NotificationRecord child = generateNotificationRecord(
2417                 mTestNotificationChannel, 2, "group", false);
2418         final NotificationRecord child2 = generateNotificationRecord(
2419                 mTestNotificationChannel, 3, "group", false);
2420         mService.addNotification(parent);
2421         mService.addNotification(child);
2422         mService.addNotification(child2);
2423         mService.getBinderService().cancelNotificationWithTag(
2424                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2425                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2426         waitForIdle();
2427         StatusBarNotification[] notifs =
2428                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2429         assertEquals(3, notifs.length);
2430     }
2431 
2432     @Test
testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild()2433     public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearChild()
2434             throws Exception {
2435         mService.isSystemUid = false;
2436         mService.isSystemAppId = false;
2437         final NotificationRecord parent = generateNotificationRecord(
2438                 mTestNotificationChannel, 1, "group", true);
2439         final NotificationRecord child = generateNotificationRecord(
2440                 mTestNotificationChannel, 2, "group", false);
2441         final NotificationRecord child2 = generateNotificationRecord(
2442                 mTestNotificationChannel, 3, "group", false);
2443         child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2444         mService.addNotification(parent);
2445         mService.addNotification(child);
2446         mService.addNotification(child2);
2447         mService.getBinderService().cancelNotificationWithTag(
2448                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2449                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2450         waitForIdle();
2451         StatusBarNotification[] notifs =
2452                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2453         assertEquals(0, notifs.length);
2454     }
2455 
2456     @Test
testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent()2457     public void testCancelNotificationWithTag_fromApp_canCancelOngoingNoClearParent()
2458             throws Exception {
2459         mService.isSystemUid = false;
2460         mService.isSystemAppId = false;
2461         final NotificationRecord parent = generateNotificationRecord(
2462                 mTestNotificationChannel, 1, "group", true);
2463         parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2464         final NotificationRecord child = generateNotificationRecord(
2465                 mTestNotificationChannel, 2, "group", false);
2466         final NotificationRecord child2 = generateNotificationRecord(
2467                 mTestNotificationChannel, 3, "group", false);
2468         mService.addNotification(parent);
2469         mService.addNotification(child);
2470         mService.addNotification(child2);
2471         mService.getBinderService().cancelNotificationWithTag(
2472                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
2473                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
2474         waitForIdle();
2475         StatusBarNotification[] notifs =
2476                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2477         assertEquals(0, notifs.length);
2478     }
2479 
2480     @Test
testCancelAllNotificationsFromApp_cannotCancelFgsChild()2481     public void testCancelAllNotificationsFromApp_cannotCancelFgsChild()
2482             throws Exception {
2483         when(mAmi.applyForegroundServiceNotification(
2484                 any(), anyString(), anyInt(), anyString(), anyInt()))
2485                 .thenReturn(SHOW_IMMEDIATELY);
2486         mService.isSystemUid = false;
2487         mService.isSystemAppId = false;
2488         final NotificationRecord parent = generateNotificationRecord(
2489                 mTestNotificationChannel, 1, "group", true);
2490         final NotificationRecord child = generateNotificationRecord(
2491                 mTestNotificationChannel, 2, "group", false);
2492         final NotificationRecord child2 = generateNotificationRecord(
2493                 mTestNotificationChannel, 3, "group", false);
2494         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2495         final NotificationRecord newGroup = generateNotificationRecord(
2496                 mTestNotificationChannel, 4, "group2", false);
2497         mService.addNotification(parent);
2498         mService.addNotification(child);
2499         mService.addNotification(child2);
2500         mService.addNotification(newGroup);
2501         mService.getBinderService().cancelAllNotifications(
2502                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2503         waitForIdle();
2504         StatusBarNotification[] notifs =
2505                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2506         assertEquals(1, notifs.length);
2507     }
2508 
2509     @Test
testCancelAllNotifications_fromApp_cannotCancelFgsParent()2510     public void testCancelAllNotifications_fromApp_cannotCancelFgsParent()
2511             throws Exception {
2512         when(mAmi.applyForegroundServiceNotification(
2513                 any(), anyString(), anyInt(), anyString(), anyInt()))
2514                 .thenReturn(SHOW_IMMEDIATELY);
2515         mService.isSystemUid = false;
2516         mService.isSystemAppId = false;
2517         final NotificationRecord parent = generateNotificationRecord(
2518                 mTestNotificationChannel, 1, "group", true);
2519         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2520         final NotificationRecord child = generateNotificationRecord(
2521                 mTestNotificationChannel, 2, "group", false);
2522         final NotificationRecord child2 = generateNotificationRecord(
2523                 mTestNotificationChannel, 3, "group", false);
2524         final NotificationRecord newGroup = generateNotificationRecord(
2525                 mTestNotificationChannel, 4, "group2", false);
2526         mService.addNotification(parent);
2527         mService.addNotification(child);
2528         mService.addNotification(child2);
2529         mService.addNotification(newGroup);
2530         mService.getBinderService().cancelAllNotifications(
2531                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2532         waitForIdle();
2533         StatusBarNotification[] notifs =
2534                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2535         assertEquals(1, notifs.length);
2536     }
2537 
2538     @Test
testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild()2539     public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearChild()
2540             throws Exception {
2541         mService.isSystemUid = false;
2542         mService.isSystemAppId = false;
2543         final NotificationRecord parent = generateNotificationRecord(
2544                 mTestNotificationChannel, 1, "group", true);
2545         final NotificationRecord child = generateNotificationRecord(
2546                 mTestNotificationChannel, 2, "group", false);
2547         final NotificationRecord child2 = generateNotificationRecord(
2548                 mTestNotificationChannel, 3, "group", false);
2549         child2.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2550         final NotificationRecord newGroup = generateNotificationRecord(
2551                 mTestNotificationChannel, 4, "group2", false);
2552         mService.addNotification(parent);
2553         mService.addNotification(child);
2554         mService.addNotification(child2);
2555         mService.addNotification(newGroup);
2556         mService.getBinderService().cancelAllNotifications(
2557                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2558         waitForIdle();
2559         StatusBarNotification[] notifs =
2560                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2561         assertEquals(0, notifs.length);
2562     }
2563 
2564     @Test
testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent()2565     public void testCancelAllNotifications_fromApp_canCancelOngoingNoClearParent()
2566             throws Exception {
2567         mService.isSystemUid = false;
2568         mService.isSystemAppId = false;
2569         final NotificationRecord parent = generateNotificationRecord(
2570                 mTestNotificationChannel, 1, "group", true);
2571         parent.getNotification().flags |= FLAG_ONGOING_EVENT | FLAG_NO_CLEAR;
2572         final NotificationRecord child = generateNotificationRecord(
2573                 mTestNotificationChannel, 2, "group", false);
2574         final NotificationRecord child2 = generateNotificationRecord(
2575                 mTestNotificationChannel, 3, "group", false);
2576         final NotificationRecord newGroup = generateNotificationRecord(
2577                 mTestNotificationChannel, 4, "group2", false);
2578         mService.addNotification(parent);
2579         mService.addNotification(child);
2580         mService.addNotification(child2);
2581         mService.addNotification(newGroup);
2582         mService.getBinderService().cancelAllNotifications(
2583                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
2584         waitForIdle();
2585         StatusBarNotification[] notifs =
2586                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2587         assertEquals(0, notifs.length);
2588     }
2589 
2590     @Test
testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent()2591     public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingParent()
2592             throws Exception {
2593         final NotificationRecord parent = generateNotificationRecord(
2594                 mTestNotificationChannel, 1, "group", true);
2595         parent.getNotification().flags |= FLAG_ONGOING_EVENT;
2596         final NotificationRecord child = generateNotificationRecord(
2597                 mTestNotificationChannel, 2, "group", false);
2598         final NotificationRecord child2 = generateNotificationRecord(
2599                 mTestNotificationChannel, 3, "group", false);
2600         final NotificationRecord newGroup = generateNotificationRecord(
2601                 mTestNotificationChannel, 4, "group2", false);
2602         mService.addNotification(parent);
2603         mService.addNotification(child);
2604         mService.addNotification(child2);
2605         mService.addNotification(newGroup);
2606         mService.getBinderService().cancelNotificationsFromListener(null, null);
2607         waitForIdle();
2608         StatusBarNotification[] notifs =
2609                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2610         assertEquals(1, notifs.length);
2611     }
2612 
2613     @Test
testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild()2614     public void testCancelNotificationsFromListener_clearAll_GroupWithOngoingChild()
2615             throws Exception {
2616         final NotificationRecord parent = generateNotificationRecord(
2617                 mTestNotificationChannel, 1, "group", true);
2618         final NotificationRecord child = generateNotificationRecord(
2619                 mTestNotificationChannel, 2, "group", false);
2620         final NotificationRecord child2 = generateNotificationRecord(
2621                 mTestNotificationChannel, 3, "group", false);
2622         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2623         final NotificationRecord newGroup = generateNotificationRecord(
2624                 mTestNotificationChannel, 4, "group2", false);
2625         mService.addNotification(parent);
2626         mService.addNotification(child);
2627         mService.addNotification(child2);
2628         mService.addNotification(newGroup);
2629         mService.getBinderService().cancelNotificationsFromListener(null, null);
2630         waitForIdle();
2631         StatusBarNotification[] notifs =
2632                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2633         assertEquals(1, notifs.length);
2634     }
2635 
2636     @Test
testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()2637     public void testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()
2638             throws Exception {
2639         when(mAmi.applyForegroundServiceNotification(
2640                 any(), anyString(), anyInt(), anyString(), anyInt()))
2641                 .thenReturn(SHOW_IMMEDIATELY);
2642         final NotificationRecord parent = generateNotificationRecord(
2643                 mTestNotificationChannel, 1, "group", true);
2644         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2645         final NotificationRecord child = generateNotificationRecord(
2646                 mTestNotificationChannel, 2, "group", false);
2647         final NotificationRecord child2 = generateNotificationRecord(
2648                 mTestNotificationChannel, 3, "group", false);
2649         final NotificationRecord newGroup = generateNotificationRecord(
2650                 mTestNotificationChannel, 4, "group2", false);
2651         mService.addNotification(parent);
2652         mService.addNotification(child);
2653         mService.addNotification(child2);
2654         mService.addNotification(newGroup);
2655         mService.getBinderService().cancelNotificationsFromListener(null, null);
2656         waitForIdle();
2657         StatusBarNotification[] notifs =
2658                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2659         assertEquals(0, notifs.length);
2660     }
2661 
2662     @Test
testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()2663     public void testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()
2664             throws Exception {
2665         when(mAmi.applyForegroundServiceNotification(
2666                 any(), anyString(), anyInt(), anyString(), anyInt()))
2667                 .thenReturn(SHOW_IMMEDIATELY);
2668         final NotificationRecord parent = generateNotificationRecord(
2669                 mTestNotificationChannel, 1, "group", true);
2670         final NotificationRecord child = generateNotificationRecord(
2671                 mTestNotificationChannel, 2, "group", false);
2672         final NotificationRecord child2 = generateNotificationRecord(
2673                 mTestNotificationChannel, 3, "group", false);
2674         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2675         final NotificationRecord newGroup = generateNotificationRecord(
2676                 mTestNotificationChannel, 4, "group2", false);
2677         mService.addNotification(parent);
2678         mService.addNotification(child);
2679         mService.addNotification(child2);
2680         mService.addNotification(newGroup);
2681         mService.getBinderService().cancelNotificationsFromListener(null, null);
2682         waitForIdle();
2683         StatusBarNotification[] notifs =
2684                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2685         assertEquals(0, notifs.length);
2686     }
2687 
2688     @Test
testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent()2689     public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearParent()
2690             throws Exception {
2691         final NotificationRecord parent = generateNotificationRecord(
2692                 mTestNotificationChannel, 1, "group", true);
2693         parent.getNotification().flags |= FLAG_NO_CLEAR;
2694         final NotificationRecord child = generateNotificationRecord(
2695                 mTestNotificationChannel, 2, "group", false);
2696         final NotificationRecord child2 = generateNotificationRecord(
2697                 mTestNotificationChannel, 3, "group", false);
2698         final NotificationRecord newGroup = generateNotificationRecord(
2699                 mTestNotificationChannel, 4, "group2", false);
2700         mService.addNotification(parent);
2701         mService.addNotification(child);
2702         mService.addNotification(child2);
2703         mService.addNotification(newGroup);
2704         mService.getBinderService().cancelNotificationsFromListener(null, null);
2705         waitForIdle();
2706         StatusBarNotification[] notifs =
2707                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2708         assertEquals(1, notifs.length);
2709     }
2710 
2711     @Test
testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild()2712     public void testCancelNotificationsFromListener_clearAll_GroupWithNoClearChild()
2713             throws Exception {
2714         final NotificationRecord parent = generateNotificationRecord(
2715                 mTestNotificationChannel, 1, "group", true);
2716         final NotificationRecord child = generateNotificationRecord(
2717                 mTestNotificationChannel, 2, "group", false);
2718         final NotificationRecord child2 = generateNotificationRecord(
2719                 mTestNotificationChannel, 3, "group", false);
2720         child2.getNotification().flags |= FLAG_NO_CLEAR;
2721         final NotificationRecord newGroup = generateNotificationRecord(
2722                 mTestNotificationChannel, 4, "group2", false);
2723         mService.addNotification(parent);
2724         mService.addNotification(child);
2725         mService.addNotification(child2);
2726         mService.addNotification(newGroup);
2727         mService.getBinderService().cancelNotificationsFromListener(null, null);
2728         waitForIdle();
2729         StatusBarNotification[] notifs =
2730                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2731         assertEquals(1, notifs.length);
2732     }
2733 
2734     @Test
testCancelNotificationsFromListener_clearAll_Ongoing()2735     public void testCancelNotificationsFromListener_clearAll_Ongoing()
2736             throws Exception {
2737         final NotificationRecord child2 = generateNotificationRecord(
2738                 mTestNotificationChannel, 3, null, false);
2739         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2740         mService.addNotification(child2);
2741         String[] keys = {child2.getSbn().getKey()};
2742         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2743         waitForIdle();
2744         StatusBarNotification[] notifs =
2745                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2746         assertEquals(1, notifs.length);
2747     }
2748 
2749     @Test
testCancelNotificationsFromListener_clearAll_NoClear()2750     public void testCancelNotificationsFromListener_clearAll_NoClear()
2751             throws Exception {
2752         final NotificationRecord child2 = generateNotificationRecord(
2753                 mTestNotificationChannel, 3, null, false);
2754         child2.getNotification().flags |= FLAG_NO_CLEAR;
2755         mService.addNotification(child2);
2756         mService.getBinderService().cancelNotificationsFromListener(null, null);
2757         waitForIdle();
2758         StatusBarNotification[] notifs =
2759                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2760         assertEquals(1, notifs.length);
2761     }
2762 
2763     @Test
testCancelNotificationsFromListener_clearAll_Fgs()2764     public void testCancelNotificationsFromListener_clearAll_Fgs()
2765             throws Exception {
2766         when(mAmi.applyForegroundServiceNotification(
2767                 any(), anyString(), anyInt(), anyString(), anyInt()))
2768                 .thenReturn(SHOW_IMMEDIATELY);
2769         final NotificationRecord child2 = generateNotificationRecord(
2770                 mTestNotificationChannel, 3, null, false);
2771         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2772         mService.addNotification(child2);
2773         mService.getBinderService().cancelNotificationsFromListener(null, null);
2774         waitForIdle();
2775         StatusBarNotification[] notifs =
2776                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2777         assertEquals(0, notifs.length);
2778     }
2779 
2780     @Test
testCancelNotificationsFromListener_byKey_GroupWithOngoingParent()2781     public void testCancelNotificationsFromListener_byKey_GroupWithOngoingParent()
2782             throws Exception {
2783         final NotificationRecord parent = generateNotificationRecord(
2784                 mTestNotificationChannel, 1, "group", true);
2785         parent.getNotification().flags |= FLAG_ONGOING_EVENT;
2786         final NotificationRecord child = generateNotificationRecord(
2787                 mTestNotificationChannel, 2, "group", false);
2788         final NotificationRecord child2 = generateNotificationRecord(
2789                 mTestNotificationChannel, 3, "group", false);
2790         final NotificationRecord newGroup = generateNotificationRecord(
2791                 mTestNotificationChannel, 4, "group2", false);
2792         mService.addNotification(parent);
2793         mService.addNotification(child);
2794         mService.addNotification(child2);
2795         mService.addNotification(newGroup);
2796         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2797                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2798         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2799         waitForIdle();
2800         StatusBarNotification[] notifs =
2801                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2802         assertEquals(1, notifs.length);
2803     }
2804 
2805     @Test
testCancelNotificationsFromListener_byKey_GroupWithOngoingChild()2806     public void testCancelNotificationsFromListener_byKey_GroupWithOngoingChild()
2807             throws Exception {
2808         final NotificationRecord parent = generateNotificationRecord(
2809                 mTestNotificationChannel, 1, "group", true);
2810         final NotificationRecord child = generateNotificationRecord(
2811                 mTestNotificationChannel, 2, "group", false);
2812         final NotificationRecord child2 = generateNotificationRecord(
2813                 mTestNotificationChannel, 3, "group", false);
2814         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2815         final NotificationRecord newGroup = generateNotificationRecord(
2816                 mTestNotificationChannel, 4, "group2", false);
2817         mService.addNotification(parent);
2818         mService.addNotification(child);
2819         mService.addNotification(child2);
2820         mService.addNotification(newGroup);
2821         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2822                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2823         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2824         waitForIdle();
2825         StatusBarNotification[] notifs =
2826                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2827         assertEquals(1, notifs.length);
2828     }
2829 
2830     @Test
testCancelNotificationsFromListener_byKey_GroupWithFgsParent()2831     public void testCancelNotificationsFromListener_byKey_GroupWithFgsParent()
2832             throws Exception {
2833         when(mAmi.applyForegroundServiceNotification(
2834                 any(), anyString(), anyInt(), anyString(), anyInt()))
2835                 .thenReturn(SHOW_IMMEDIATELY);
2836         final NotificationRecord parent = generateNotificationRecord(
2837                 mTestNotificationChannel, 1, "group", true);
2838         parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2839         final NotificationRecord child = generateNotificationRecord(
2840                 mTestNotificationChannel, 2, "group", false);
2841         final NotificationRecord child2 = generateNotificationRecord(
2842                 mTestNotificationChannel, 3, "group", false);
2843         final NotificationRecord newGroup = generateNotificationRecord(
2844                 mTestNotificationChannel, 4, "group2", false);
2845         mService.addNotification(parent);
2846         mService.addNotification(child);
2847         mService.addNotification(child2);
2848         mService.addNotification(newGroup);
2849         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2850                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2851         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2852         waitForIdle();
2853         StatusBarNotification[] notifs =
2854                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2855         assertEquals(0, notifs.length);
2856     }
2857 
2858     @Test
testCancelNotificationsFromListener_byKey_GroupWithFgsChild()2859     public void testCancelNotificationsFromListener_byKey_GroupWithFgsChild()
2860             throws Exception {
2861         when(mAmi.applyForegroundServiceNotification(
2862                 any(), anyString(), anyInt(), anyString(), anyInt()))
2863                 .thenReturn(SHOW_IMMEDIATELY);
2864         final NotificationRecord parent = generateNotificationRecord(
2865                 mTestNotificationChannel, 1, "group", true);
2866         final NotificationRecord child = generateNotificationRecord(
2867                 mTestNotificationChannel, 2, "group", false);
2868         final NotificationRecord child2 = generateNotificationRecord(
2869                 mTestNotificationChannel, 3, "group", false);
2870         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2871         final NotificationRecord newGroup = generateNotificationRecord(
2872                 mTestNotificationChannel, 4, "group2", false);
2873         mService.addNotification(parent);
2874         mService.addNotification(child);
2875         mService.addNotification(child2);
2876         mService.addNotification(newGroup);
2877         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2878                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2879         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2880         waitForIdle();
2881         StatusBarNotification[] notifs =
2882                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2883         assertEquals(0, notifs.length);
2884     }
2885 
2886     @Test
testCancelNotificationsFromListener_byKey_GroupWithNoClearParent()2887     public void testCancelNotificationsFromListener_byKey_GroupWithNoClearParent()
2888             throws Exception {
2889         final NotificationRecord parent = generateNotificationRecord(
2890                 mTestNotificationChannel, 1, "group", true);
2891         parent.getNotification().flags |= FLAG_NO_CLEAR;
2892         final NotificationRecord child = generateNotificationRecord(
2893                 mTestNotificationChannel, 2, "group", false);
2894         final NotificationRecord child2 = generateNotificationRecord(
2895                 mTestNotificationChannel, 3, "group", false);
2896         final NotificationRecord newGroup = generateNotificationRecord(
2897                 mTestNotificationChannel, 4, "group2", false);
2898         mService.addNotification(parent);
2899         mService.addNotification(child);
2900         mService.addNotification(child2);
2901         mService.addNotification(newGroup);
2902         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2903                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2904         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2905         waitForIdle();
2906         StatusBarNotification[] notifs =
2907                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2908         assertEquals(0, notifs.length);
2909     }
2910 
2911     @Test
testCancelNotificationsFromListener_byKey_GroupWithNoClearChild()2912     public void testCancelNotificationsFromListener_byKey_GroupWithNoClearChild()
2913             throws Exception {
2914         final NotificationRecord parent = generateNotificationRecord(
2915                 mTestNotificationChannel, 1, "group", true);
2916         final NotificationRecord child = generateNotificationRecord(
2917                 mTestNotificationChannel, 2, "group", false);
2918         final NotificationRecord child2 = generateNotificationRecord(
2919                 mTestNotificationChannel, 3, "group", false);
2920         child2.getNotification().flags |= FLAG_NO_CLEAR;
2921         final NotificationRecord newGroup = generateNotificationRecord(
2922                 mTestNotificationChannel, 4, "group2", false);
2923         mService.addNotification(parent);
2924         mService.addNotification(child);
2925         mService.addNotification(child2);
2926         mService.addNotification(newGroup);
2927         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2928                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
2929         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2930         waitForIdle();
2931         StatusBarNotification[] notifs =
2932                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
2933         assertEquals(0, notifs.length);
2934     }
2935 
2936     @Test
testCancelNotificationsFromListener_byKey_Ongoing()2937     public void testCancelNotificationsFromListener_byKey_Ongoing()
2938             throws Exception {
2939         final NotificationRecord child2 = generateNotificationRecord(
2940                 mTestNotificationChannel, 3, null, false);
2941         child2.getNotification().flags |= FLAG_ONGOING_EVENT;
2942         mService.addNotification(child2);
2943         String[] keys = {child2.getSbn().getKey()};
2944         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2945         waitForIdle();
2946         StatusBarNotification[] notifs =
2947                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2948         assertEquals(1, notifs.length);
2949     }
2950 
2951     @Test
testCancelNotificationsFromListener_byKey_NoClear()2952     public void testCancelNotificationsFromListener_byKey_NoClear()
2953             throws Exception {
2954         final NotificationRecord child2 = generateNotificationRecord(
2955                 mTestNotificationChannel, 3, null, false);
2956         child2.getNotification().flags |= FLAG_NO_CLEAR;
2957         mService.addNotification(child2);
2958         String[] keys = {child2.getSbn().getKey()};
2959         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2960         waitForIdle();
2961         StatusBarNotification[] notifs =
2962                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2963         assertEquals(0, notifs.length);
2964     }
2965 
2966     @Test
testCancelNotificationsFromListener_byKey_Fgs()2967     public void testCancelNotificationsFromListener_byKey_Fgs()
2968             throws Exception {
2969         when(mAmi.applyForegroundServiceNotification(
2970                 any(), anyString(), anyInt(), anyString(), anyInt()))
2971                 .thenReturn(SHOW_IMMEDIATELY);
2972         final NotificationRecord child2 = generateNotificationRecord(
2973                 mTestNotificationChannel, 3, null, false);
2974         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
2975         mService.addNotification(child2);
2976         String[] keys = {child2.getSbn().getKey()};
2977         mService.getBinderService().cancelNotificationsFromListener(null, keys);
2978         waitForIdle();
2979         StatusBarNotification[] notifs =
2980                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
2981         assertEquals(0, notifs.length);
2982     }
2983 
2984     @Test
testGroupInstanceIds()2985     public void testGroupInstanceIds() throws Exception {
2986         final NotificationRecord group1 = generateNotificationRecord(
2987                 mTestNotificationChannel, 1, "group1", true);
2988         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds",
2989                 group1.getSbn().getId(), group1.getSbn().getNotification(),
2990                 group1.getSbn().getUserId());
2991         waitForIdle();
2992 
2993         // same group, child, should be returned
2994         final NotificationRecord group1Child = generateNotificationRecord(
2995                 mTestNotificationChannel, 2, "group1", false);
2996         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testGroupInstanceIds",
2997                 group1Child.getSbn().getId(),
2998                 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
2999         waitForIdle();
3000 
3001         assertEquals(2, mNotificationRecordLogger.numCalls());
3002         assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
3003                 mNotificationRecordLogger.get(1).groupInstanceId.getId());
3004     }
3005 
3006     @Test
testFindGroupNotificationsLocked()3007     public void testFindGroupNotificationsLocked() throws Exception {
3008         // make sure the same notification can be found in both lists and returned
3009         final NotificationRecord group1 = generateNotificationRecord(
3010                 mTestNotificationChannel, 1, "group1", true);
3011         mService.addEnqueuedNotification(group1);
3012         mService.addNotification(group1);
3013 
3014         // should not be returned
3015         final NotificationRecord group2 = generateNotificationRecord(
3016                 mTestNotificationChannel, 2, "group2", true);
3017         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
3018                 group2.getSbn().getId(), group2.getSbn().getNotification(),
3019                 group2.getSbn().getUserId());
3020         waitForIdle();
3021 
3022         // should not be returned
3023         final NotificationRecord nonGroup = generateNotificationRecord(
3024                 mTestNotificationChannel, 3, null, false);
3025         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
3026                 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
3027                 nonGroup.getSbn().getUserId());
3028         waitForIdle();
3029 
3030         // same group, child, should be returned
3031         final NotificationRecord group1Child = generateNotificationRecord(
3032                 mTestNotificationChannel, 4, "group1", false);
3033         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
3034                 group1Child.getSbn().getId(),
3035                 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
3036         waitForIdle();
3037 
3038         List<NotificationRecord> inGroup1 =
3039                 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
3040                         group1.getSbn().getUserId());
3041         assertEquals(3, inGroup1.size());
3042         for (NotificationRecord record : inGroup1) {
3043             assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
3044             assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
3045         }
3046     }
3047 
3048     @Test
testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing()3049     public void testCancelAllNotificationsInt_CancelsNoClearFlagOnGoing() throws Exception {
3050         final NotificationRecord notif = generateNotificationRecord(
3051                 mTestNotificationChannel, 1, "group", true);
3052         notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
3053         mService.addNotification(notif);
3054         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
3055                 Notification.FLAG_ONGOING_EVENT, notif.getUserId(), REASON_CANCEL);
3056         waitForIdle();
3057         StatusBarNotification[] notifs =
3058                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
3059         assertEquals(0, notifs.length);
3060     }
3061 
3062     @Test
testAppInitiatedCancelAllNotifications_CancelsOngoingFlag()3063     public void testAppInitiatedCancelAllNotifications_CancelsOngoingFlag() throws Exception {
3064         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
3065         sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
3066         mBinderService.enqueueNotificationWithTag(PKG, PKG,
3067                 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
3068                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3069         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
3070         waitForIdle();
3071         StatusBarNotification[] notifs =
3072                 mBinderService.getActiveNotifications(sbn.getPackageName());
3073         assertEquals(0, notifs.length);
3074     }
3075 
3076     @Test
testCancelAllNotificationsInt_CancelsOngoingFlag()3077     public void testCancelAllNotificationsInt_CancelsOngoingFlag() throws Exception {
3078         final NotificationRecord notif = generateNotificationRecord(
3079                 mTestNotificationChannel, 1, "group", true);
3080         notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
3081         mService.addNotification(notif);
3082         mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0,
3083                 notif.getUserId(), REASON_CANCEL);
3084         waitForIdle();
3085         StatusBarNotification[] notifs =
3086                 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
3087         assertEquals(0, notifs.length);
3088     }
3089 
3090     @Test
testUserInitiatedCancelAllWithGroup_OngoingFlag()3091     public void testUserInitiatedCancelAllWithGroup_OngoingFlag() throws Exception {
3092         final NotificationRecord parent = generateNotificationRecord(
3093                 mTestNotificationChannel, 1, "group", true);
3094         final NotificationRecord child = generateNotificationRecord(
3095                 mTestNotificationChannel, 2, "group", false);
3096         final NotificationRecord child2 = generateNotificationRecord(
3097                 mTestNotificationChannel, 3, "group", false);
3098         child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
3099         final NotificationRecord newGroup = generateNotificationRecord(
3100                 mTestNotificationChannel, 4, "group2", false);
3101         mService.addNotification(parent);
3102         mService.addNotification(child);
3103         mService.addNotification(child2);
3104         mService.addNotification(newGroup);
3105         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
3106                 parent.getUserId());
3107         waitForIdle();
3108         StatusBarNotification[] notifs =
3109                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
3110         assertEquals(1, notifs.length);
3111     }
3112 
3113     @Test
testUserInitiatedCancelAllWithGroup_NoClearFlag()3114     public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
3115         final NotificationRecord parent = generateNotificationRecord(
3116                 mTestNotificationChannel, 1, "group", true);
3117         final NotificationRecord child = generateNotificationRecord(
3118                 mTestNotificationChannel, 2, "group", false);
3119         final NotificationRecord child2 = generateNotificationRecord(
3120                 mTestNotificationChannel, 3, "group", false);
3121         child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
3122         final NotificationRecord newGroup = generateNotificationRecord(
3123                 mTestNotificationChannel, 4, "group2", false);
3124         mService.addNotification(parent);
3125         mService.addNotification(child);
3126         mService.addNotification(child2);
3127         mService.addNotification(newGroup);
3128         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
3129                 parent.getUserId());
3130         waitForIdle();
3131         StatusBarNotification[] notifs =
3132                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
3133         assertEquals(1, notifs.length);
3134     }
3135 
3136     @Test
testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag()3137     public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
3138         when(mAmi.applyForegroundServiceNotification(
3139                 any(), anyString(), anyInt(), anyString(), anyInt()))
3140                 .thenReturn(SHOW_IMMEDIATELY);
3141         final NotificationRecord parent = generateNotificationRecord(
3142                 mTestNotificationChannel, 1, "group", true);
3143         final NotificationRecord child = generateNotificationRecord(
3144                 mTestNotificationChannel, 2, "group", false);
3145         final NotificationRecord child2 = generateNotificationRecord(
3146                 mTestNotificationChannel, 3, "group", false);
3147         child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
3148         final NotificationRecord newGroup = generateNotificationRecord(
3149                 mTestNotificationChannel, 4, "group2", false);
3150         mService.addNotification(parent);
3151         mService.addNotification(child);
3152         mService.addNotification(child2);
3153         mService.addNotification(newGroup);
3154         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
3155                 parent.getUserId());
3156         waitForIdle();
3157         StatusBarNotification[] notifs =
3158                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
3159         assertEquals(0, notifs.length);
3160     }
3161 
3162     @Test
testDefaultChannelUpdatesApp_postMigrationToPermissions()3163     public void testDefaultChannelUpdatesApp_postMigrationToPermissions() throws Exception {
3164         final NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
3165                 PKG_N_MR1, ActivityManager.getCurrentUser(), PKG_N_MR1,
3166                 NotificationChannel.DEFAULT_CHANNEL_ID);
3167         defaultChannel.setImportance(IMPORTANCE_NONE);
3168 
3169         mBinderService.updateNotificationChannelForPackage(PKG_N_MR1, mUid, defaultChannel);
3170 
3171         verify(mPermissionHelper).setNotificationPermission(
3172                 PKG_N_MR1, ActivityManager.getCurrentUser(), false, true);
3173     }
3174 
3175     @Test
testPostNotification_appPermissionFixed()3176     public void testPostNotification_appPermissionFixed() throws Exception {
3177         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
3178         when(mPermissionHelper.isPermissionFixed(PKG, 0)).thenReturn(true);
3179 
3180         NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel);
3181         mBinderService.enqueueNotificationWithTag(PKG, PKG,
3182                 "testPostNotification_appPermissionFixed", 0,
3183                 temp.getNotification(), 0);
3184         waitForIdle();
3185         assertThat(mService.getNotificationRecordCount()).isEqualTo(1);
3186         StatusBarNotification[] notifs =
3187                 mBinderService.getActiveNotifications(PKG);
3188         assertThat(mService.getNotificationRecord(notifs[0].getKey()).isImportanceFixed()).isTrue();
3189     }
3190 
3191     @Test
testSummaryNotification_appPermissionFixed()3192     public void testSummaryNotification_appPermissionFixed() {
3193         NotificationRecord temp = generateNotificationRecord(mTestNotificationChannel);
3194         mService.addNotification(temp);
3195 
3196         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
3197         when(mPermissionHelper.isPermissionFixed(PKG, temp.getUserId())).thenReturn(true);
3198 
3199         NotificationRecord r = mService.createAutoGroupSummary(
3200                 temp.getUserId(), temp.getSbn().getPackageName(), temp.getKey(), 0);
3201 
3202         assertThat(r.isImportanceFixed()).isTrue();
3203     }
3204 
3205     @Test
testTvExtenderChannelOverride_onTv()3206     public void testTvExtenderChannelOverride_onTv() throws Exception {
3207         mService.setIsTelevision(true);
3208         mService.setPreferencesHelper(mPreferencesHelper);
3209         when(mPreferencesHelper.getNotificationChannel(
3210                 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
3211                         new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
3212 
3213         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
3214         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
3215                 generateNotificationRecord(null, tv).getNotification(), 0);
3216         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
3217                 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
3218     }
3219 
3220     @Test
testTvExtenderChannelOverride_notOnTv()3221     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
3222         mService.setIsTelevision(false);
3223         mService.setPreferencesHelper(mPreferencesHelper);
3224         when(mPreferencesHelper.getNotificationChannel(
3225                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
3226                 mTestNotificationChannel);
3227 
3228         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
3229         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
3230                 0, generateNotificationRecord(null, tv).getNotification(), 0);
3231         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
3232                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
3233                 anyBoolean(), anyBoolean());
3234     }
3235 
3236     @Test
onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()3237     public void onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()
3238             throws RemoteException {
3239         // Have preexisting posted notifications from revoked package and other packages.
3240         mService.addNotification(new NotificationRecord(mContext,
3241                 generateSbn("revoked", 1001, 1, 0), mTestNotificationChannel));
3242         mService.addNotification(new NotificationRecord(mContext,
3243                 generateSbn("other", 1002, 2, 0), mTestNotificationChannel));
3244         // Have preexisting enqueued notifications from revoked package and other packages.
3245         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3246                 generateSbn("revoked", 1001, 3, 0), mTestNotificationChannel));
3247         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3248                 generateSbn("other", 1002, 4, 0), mTestNotificationChannel));
3249         assertThat(mService.mNotificationList).hasSize(2);
3250         assertThat(mService.mEnqueuedNotifications).hasSize(2);
3251 
3252         when(mPackageManagerInternal.getPackageUid("revoked", 0, 0)).thenReturn(1001);
3253         when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(false);
3254 
3255         mOnPermissionChangeListener.onOpChanged(
3256                 AppOpsManager.OPSTR_POST_NOTIFICATION, "revoked", 0);
3257         waitForIdle();
3258 
3259         assertThat(mService.mNotificationList).hasSize(1);
3260         assertThat(mService.mNotificationList.get(0).getSbn().getPackageName()).isEqualTo("other");
3261         assertThat(mService.mEnqueuedNotifications).hasSize(1);
3262         assertThat(mService.mEnqueuedNotifications.get(0).getSbn().getPackageName()).isEqualTo(
3263                 "other");
3264     }
3265 
3266     @Test
onOpChanged_permissionStillGranted_notificationsAreNotAffected()3267     public void onOpChanged_permissionStillGranted_notificationsAreNotAffected()
3268             throws RemoteException {
3269         // NOTE: This combination (receiving the onOpChanged broadcast for a package, the permission
3270         // being now granted, AND having previously posted notifications from said package) should
3271         // never happen (if we trust the broadcasts are correct). So this test is for a what-if
3272         // scenario, to verify we still handle it reasonably.
3273 
3274         // Have preexisting posted notifications from specific package and other packages.
3275         mService.addNotification(new NotificationRecord(mContext,
3276                 generateSbn("granted", 1001, 1, 0), mTestNotificationChannel));
3277         mService.addNotification(new NotificationRecord(mContext,
3278                 generateSbn("other", 1002, 2, 0), mTestNotificationChannel));
3279         // Have preexisting enqueued notifications from specific package and other packages.
3280         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3281                 generateSbn("granted", 1001, 3, 0), mTestNotificationChannel));
3282         mService.addEnqueuedNotification(new NotificationRecord(mContext,
3283                 generateSbn("other", 1002, 4, 0), mTestNotificationChannel));
3284         assertThat(mService.mNotificationList).hasSize(2);
3285         assertThat(mService.mEnqueuedNotifications).hasSize(2);
3286 
3287         when(mPackageManagerInternal.getPackageUid("granted", 0, 0)).thenReturn(1001);
3288         when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(true);
3289 
3290         mOnPermissionChangeListener.onOpChanged(
3291                 AppOpsManager.OPSTR_POST_NOTIFICATION, "granted", 0);
3292         waitForIdle();
3293 
3294         assertThat(mService.mNotificationList).hasSize(2);
3295         assertThat(mService.mEnqueuedNotifications).hasSize(2);
3296     }
3297 
3298     @Test
onOpChanged_notInitializedUser_ignored()3299     public void onOpChanged_notInitializedUser_ignored() throws RemoteException {
3300         when(mUmInternal.isUserInitialized(eq(0))).thenReturn(false);
3301 
3302         mOnPermissionChangeListener.onOpChanged(
3303                 AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0);
3304         waitForIdle();
3305 
3306         // We early-exited and didn't even query PM for package details.
3307         verify(mPackageManagerInternal, never()).getPackageUid(any(), anyLong(), anyInt());
3308     }
3309 
3310     @Test
setNotificationsEnabledForPackage_disabling_clearsNotifications()3311     public void setNotificationsEnabledForPackage_disabling_clearsNotifications() throws Exception {
3312         mService.addNotification(new NotificationRecord(mContext,
3313                 generateSbn("package", 1001, 1, 0), mTestNotificationChannel));
3314         assertThat(mService.mNotificationList).hasSize(1);
3315         when(mPackageManagerInternal.getPackageUid("package", 0, 0)).thenReturn(1001);
3316         when(mPermissionHelper.hasRequestedPermission(any(), eq("package"), anyInt())).thenReturn(
3317                 true);
3318 
3319         // Start with granted permission and simulate effect of revoking it.
3320         when(mPermissionHelper.hasPermission(1001)).thenReturn(true);
3321         doAnswer(invocation -> {
3322             when(mPermissionHelper.hasPermission(1001)).thenReturn(false);
3323             mOnPermissionChangeListener.onOpChanged(
3324                     AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0);
3325             return null;
3326         }).when(mPermissionHelper).setNotificationPermission("package", 0, false, true);
3327 
3328         mBinderService.setNotificationsEnabledForPackage("package", 1001, false);
3329         waitForIdle();
3330 
3331         assertThat(mService.mNotificationList).hasSize(0);
3332 
3333         mTestableLooper.moveTimeForward(500);
3334         waitForIdle();
3335         verify(mContext).sendBroadcastAsUser(any(), eq(UserHandle.of(0)), eq(null));
3336     }
3337 
3338     @Test
testUpdateAppNotifyCreatorBlock()3339     public void testUpdateAppNotifyCreatorBlock() throws Exception {
3340         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
3341 
3342         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
3343         Thread.sleep(500);
3344         waitForIdle();
3345 
3346         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3347         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3348 
3349         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
3350                 captor.getValue().getAction());
3351         assertEquals(PKG, captor.getValue().getPackage());
3352         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
3353     }
3354 
3355     @Test
testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting()3356     public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
3357         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
3358 
3359         mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
3360         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
3361     }
3362 
3363     @Test
testUpdateAppNotifyCreatorUnblock()3364     public void testUpdateAppNotifyCreatorUnblock() throws Exception {
3365         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
3366 
3367         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, true);
3368         Thread.sleep(500);
3369         waitForIdle();
3370 
3371         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3372         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3373 
3374         assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
3375                 captor.getValue().getAction());
3376         assertEquals(PKG, captor.getValue().getPackage());
3377         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
3378     }
3379 
3380     @Test
testUpdateChannelNotifyCreatorBlock()3381     public void testUpdateChannelNotifyCreatorBlock() throws Exception {
3382         mService.setPreferencesHelper(mPreferencesHelper);
3383         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3384                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3385                 .thenReturn(mTestNotificationChannel);
3386 
3387         NotificationChannel updatedChannel =
3388                 new NotificationChannel(mTestNotificationChannel.getId(),
3389                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
3390 
3391         mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
3392         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3393         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3394 
3395         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
3396                 captor.getValue().getAction());
3397         assertEquals(PKG, captor.getValue().getPackage());
3398         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
3399                         NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
3400         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3401     }
3402 
3403     @Test
testUpdateChannelNotifyCreatorUnblock()3404     public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
3405         NotificationChannel existingChannel =
3406                 new NotificationChannel(mTestNotificationChannel.getId(),
3407                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
3408         mService.setPreferencesHelper(mPreferencesHelper);
3409         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3410                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3411                 .thenReturn(existingChannel);
3412 
3413         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
3414         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3415         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3416 
3417         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
3418                 captor.getValue().getAction());
3419         assertEquals(PKG, captor.getValue().getPackage());
3420         assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
3421                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
3422         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3423     }
3424 
3425     @Test
testUpdateChannelNoNotifyCreatorOtherChanges()3426     public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
3427         NotificationChannel existingChannel =
3428                 new NotificationChannel(mTestNotificationChannel.getId(),
3429                         mTestNotificationChannel.getName(), IMPORTANCE_MAX);
3430         mService.setPreferencesHelper(mPreferencesHelper);
3431         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3432                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3433                 .thenReturn(existingChannel);
3434 
3435         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
3436         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
3437     }
3438 
3439     @Test
testUpdateGroupNotifyCreatorBlock()3440     public void testUpdateGroupNotifyCreatorBlock() throws Exception {
3441         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
3442         mService.setPreferencesHelper(mPreferencesHelper);
3443         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
3444                 eq(PKG), anyInt()))
3445                 .thenReturn(existing);
3446 
3447         NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
3448         updated.setBlocked(true);
3449 
3450         mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
3451         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3452         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3453 
3454         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
3455                 captor.getValue().getAction());
3456         assertEquals(PKG, captor.getValue().getPackage());
3457         assertEquals(existing.getId(), captor.getValue().getStringExtra(
3458                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
3459         assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3460     }
3461 
3462     @Test
testUpdateGroupNotifyCreatorUnblock()3463     public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
3464         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
3465         existing.setBlocked(true);
3466         mService.setPreferencesHelper(mPreferencesHelper);
3467         when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
3468                 eq(PKG), anyInt()))
3469                 .thenReturn(existing);
3470 
3471         mBinderService.updateNotificationChannelGroupForPackage(
3472                 PKG, 0, new NotificationChannelGroup("id", "name"));
3473         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
3474         verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
3475 
3476         assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
3477                 captor.getValue().getAction());
3478         assertEquals(PKG, captor.getValue().getPackage());
3479         assertEquals(existing.getId(), captor.getValue().getStringExtra(
3480                 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
3481         assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
3482     }
3483 
3484     @Test
testUpdateGroupNoNotifyCreatorOtherChanges()3485     public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
3486         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
3487         mService.setPreferencesHelper(mPreferencesHelper);
3488         when(mPreferencesHelper.getNotificationChannelGroup(
3489                 eq(existing.getId()), eq(PKG), anyInt()))
3490                 .thenReturn(existing);
3491 
3492         mBinderService.updateNotificationChannelGroupForPackage(
3493                 PKG, 0, new NotificationChannelGroup("id", "new name"));
3494         verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
3495     }
3496 
3497     @Test
testCreateChannelNotifyListener()3498     public void testCreateChannelNotifyListener() throws Exception {
3499         when(mCompanionMgr.getAssociations(PKG, mUserId))
3500                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3501         mService.setPreferencesHelper(mPreferencesHelper);
3502         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3503                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3504                 .thenReturn(mTestNotificationChannel);
3505         NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
3506         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3507                 eq(channel2.getId()), anyBoolean()))
3508                 .thenReturn(channel2);
3509         when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
3510                 eq(channel2), anyBoolean(), anyBoolean(), anyInt(), anyBoolean()))
3511                 .thenReturn(true);
3512 
3513         reset(mListeners);
3514         mBinderService.createNotificationChannels(PKG,
3515                 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
3516         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3517                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3518                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3519         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
3520                 eq(Process.myUserHandle()), eq(channel2),
3521                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3522     }
3523 
3524     @Test
testCreateChannelGroupNotifyListener()3525     public void testCreateChannelGroupNotifyListener() throws Exception {
3526         when(mCompanionMgr.getAssociations(PKG, mUserId))
3527                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3528         mService.setPreferencesHelper(mPreferencesHelper);
3529         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
3530         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
3531 
3532         reset(mListeners);
3533         mBinderService.createNotificationChannelGroups(PKG,
3534                 new ParceledListSlice(Arrays.asList(group1, group2)));
3535         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
3536                 eq(Process.myUserHandle()), eq(group1),
3537                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3538         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
3539                 eq(Process.myUserHandle()), eq(group2),
3540                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
3541     }
3542 
3543     @Test
testUpdateChannelNotifyListener()3544     public void testUpdateChannelNotifyListener() throws Exception {
3545         when(mCompanionMgr.getAssociations(PKG, mUserId))
3546                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3547         mService.setPreferencesHelper(mPreferencesHelper);
3548         mTestNotificationChannel.setLightColor(Color.CYAN);
3549         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3550                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3551                 .thenReturn(mTestNotificationChannel);
3552 
3553         reset(mListeners);
3554         mBinderService.updateNotificationChannelForPackage(PKG, mUid, mTestNotificationChannel);
3555         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
3556                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3557                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3558     }
3559 
3560     @Test
testDeleteChannelNotifyListener()3561     public void testDeleteChannelNotifyListener() throws Exception {
3562         when(mCompanionMgr.getAssociations(PKG, mUserId))
3563                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3564         mService.setPreferencesHelper(mPreferencesHelper);
3565         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3566                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3567                 .thenReturn(mTestNotificationChannel);
3568         when(mPreferencesHelper.deleteNotificationChannel(eq(PKG), anyInt(),
3569                 eq(mTestNotificationChannel.getId()),  anyInt(), anyBoolean())).thenReturn(true);
3570         reset(mListeners);
3571         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
3572         verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
3573                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3574                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
3575     }
3576 
3577     @Test
testDeleteChannelOnlyDoExtraWorkIfExisted()3578     public void testDeleteChannelOnlyDoExtraWorkIfExisted() throws Exception {
3579         when(mCompanionMgr.getAssociations(PKG, mUserId))
3580                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3581         mService.setPreferencesHelper(mPreferencesHelper);
3582         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3583                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3584                 .thenReturn(null);
3585         reset(mListeners);
3586         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
3587         verifyNoMoreInteractions(mListeners);
3588         verifyNoMoreInteractions(mHistoryManager);
3589     }
3590 
3591     @Test
testDeleteChannelGroupNotifyListener()3592     public void testDeleteChannelGroupNotifyListener() throws Exception {
3593         when(mCompanionMgr.getAssociations(PKG, mUserId))
3594                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3595         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
3596         mService.setPreferencesHelper(mPreferencesHelper);
3597         when(mPreferencesHelper.getNotificationChannelGroupWithChannels(
3598                 eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean()))
3599                 .thenReturn(ncg);
3600         reset(mListeners);
3601         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
3602         verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
3603                 eq(Process.myUserHandle()), eq(ncg),
3604                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
3605     }
3606 
3607     @Test
testDeleteChannelGroupChecksForFgses()3608     public void testDeleteChannelGroupChecksForFgses() throws Exception {
3609         when(mCompanionMgr.getAssociations(PKG, mUserId))
3610                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3611         CountDownLatch latch = new CountDownLatch(2);
3612         mService.createNotificationChannelGroup(
3613                 PKG, mUid, new NotificationChannelGroup("group", "group"), true, false);
3614         new Thread(() -> {
3615             NotificationChannel notificationChannel = new NotificationChannel("id", "id",
3616                     NotificationManager.IMPORTANCE_HIGH);
3617             notificationChannel.setGroup("group");
3618             ParceledListSlice<NotificationChannel> pls =
3619                     new ParceledListSlice(ImmutableList.of(notificationChannel));
3620             try {
3621                 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
3622             } catch (RemoteException e) {
3623                 throw new RuntimeException(e);
3624             }
3625             latch.countDown();
3626         }).start();
3627         new Thread(() -> {
3628             try {
3629                 synchronized (this) {
3630                     wait(5000);
3631                 }
3632                 mService.createNotificationChannelGroup(PKG, mUid,
3633                         new NotificationChannelGroup("new", "new group"), true, false);
3634                 NotificationChannel notificationChannel =
3635                         new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
3636                 notificationChannel.setGroup("new");
3637                 ParceledListSlice<NotificationChannel> pls =
3638                         new ParceledListSlice(ImmutableList.of(notificationChannel));
3639                 try {
3640                 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
3641                 mBinderService.deleteNotificationChannelGroup(PKG, "group");
3642                 } catch (RemoteException e) {
3643                     throw new RuntimeException(e);
3644                 }
3645             } catch (Exception e) {
3646                 e.printStackTrace();
3647             }
3648             latch.countDown();
3649         }).start();
3650 
3651         latch.await();
3652         verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString());
3653     }
3654 
3655     @Test
testUpdateNotificationChannelFromPrivilegedListener_success()3656     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
3657         mService.setPreferencesHelper(mPreferencesHelper);
3658         when(mCompanionMgr.getAssociations(PKG, mUserId))
3659                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3660         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
3661                 eq(mTestNotificationChannel.getId()), anyBoolean()))
3662                 .thenReturn(mTestNotificationChannel);
3663 
3664         mBinderService.updateNotificationChannelFromPrivilegedListener(
3665                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
3666 
3667         verify(mPreferencesHelper, times(1)).updateNotificationChannel(
3668                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3669 
3670         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3671                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3672                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3673     }
3674 
3675     @Test
testUpdateNotificationChannelFromPrivilegedListener_noAccess()3676     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
3677         mService.setPreferencesHelper(mPreferencesHelper);
3678         when(mCompanionMgr.getAssociations(PKG, mUserId))
3679                 .thenReturn(emptyList());
3680 
3681         try {
3682             mBinderService.updateNotificationChannelFromPrivilegedListener(
3683                     null, PKG, Process.myUserHandle(), mTestNotificationChannel);
3684             fail("listeners that don't have a companion device shouldn't be able to call this");
3685         } catch (SecurityException e) {
3686             // pass
3687         }
3688 
3689         verify(mPreferencesHelper, never()).updateNotificationChannel(
3690                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3691 
3692         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3693                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3694                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3695     }
3696 
3697     @Test
testUpdateNotificationChannelFromPrivilegedListener_badUser()3698     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
3699         mService.setPreferencesHelper(mPreferencesHelper);
3700         when(mCompanionMgr.getAssociations(PKG, mUserId))
3701                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3702         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3703         mListener.component = new ComponentName(PKG, PKG);
3704         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3705         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3706 
3707         try {
3708             mBinderService.updateNotificationChannelFromPrivilegedListener(
3709                     null, PKG, UserHandle.ALL, mTestNotificationChannel);
3710             fail("incorrectly allowed a change to a user listener cannot see");
3711         } catch (SecurityException e) {
3712             // pass
3713         }
3714 
3715         verify(mPreferencesHelper, never()).updateNotificationChannel(
3716                 anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
3717 
3718         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
3719                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
3720                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
3721     }
3722 
3723     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_success()3724     public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
3725         mService.setPreferencesHelper(mPreferencesHelper);
3726         when(mCompanionMgr.getAssociations(PKG, mUserId))
3727                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3728 
3729         mBinderService.getNotificationChannelsFromPrivilegedListener(
3730                 null, PKG, Process.myUserHandle());
3731 
3732         verify(mPreferencesHelper, times(1)).getNotificationChannels(
3733                 anyString(), anyInt(), anyBoolean());
3734     }
3735 
3736     @Test
testGetNotificationChannelFromPrivilegedListener_cdm_noAccess()3737     public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
3738         mService.setPreferencesHelper(mPreferencesHelper);
3739         when(mCompanionMgr.getAssociations(PKG, mUserId))
3740                 .thenReturn(emptyList());
3741 
3742         try {
3743             mBinderService.getNotificationChannelsFromPrivilegedListener(
3744                     null, PKG, Process.myUserHandle());
3745             fail("listeners that don't have a companion device shouldn't be able to call this");
3746         } catch (SecurityException e) {
3747             // pass
3748         }
3749 
3750         verify(mPreferencesHelper, never()).getNotificationChannels(
3751                 anyString(), anyInt(), anyBoolean());
3752     }
3753 
3754     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_success()3755     public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
3756             throws Exception {
3757         mService.setPreferencesHelper(mPreferencesHelper);
3758         when(mCompanionMgr.getAssociations(PKG, mUserId))
3759                 .thenReturn(emptyList());
3760         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
3761 
3762         mBinderService.getNotificationChannelsFromPrivilegedListener(
3763                 null, PKG, Process.myUserHandle());
3764 
3765         verify(mPreferencesHelper, times(1)).getNotificationChannels(
3766                 anyString(), anyInt(), anyBoolean());
3767     }
3768 
3769     @Test
testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()3770     public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
3771             throws Exception {
3772         mService.setPreferencesHelper(mPreferencesHelper);
3773         when(mCompanionMgr.getAssociations(PKG, mUserId))
3774                 .thenReturn(emptyList());
3775         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
3776 
3777         try {
3778             mBinderService.getNotificationChannelsFromPrivilegedListener(
3779                     null, PKG, Process.myUserHandle());
3780             fail("listeners that don't have a companion device shouldn't be able to call this");
3781         } catch (SecurityException e) {
3782             // pass
3783         }
3784 
3785         verify(mPreferencesHelper, never()).getNotificationChannels(
3786                 anyString(), anyInt(), anyBoolean());
3787     }
3788 
3789     @Test
testGetNotificationChannelFromPrivilegedListener_badUser()3790     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
3791         mService.setPreferencesHelper(mPreferencesHelper);
3792         when(mCompanionMgr.getAssociations(PKG, mUserId))
3793                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3794         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3795         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3796         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3797 
3798         try {
3799             mBinderService.getNotificationChannelsFromPrivilegedListener(
3800                     null, PKG, Process.myUserHandle());
3801             fail("listener getting channels from a user they cannot see");
3802         } catch (SecurityException e) {
3803             // pass
3804         }
3805 
3806         verify(mPreferencesHelper, never()).getNotificationChannels(
3807                 anyString(), anyInt(), anyBoolean());
3808     }
3809 
3810     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_success()3811     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
3812         mService.setPreferencesHelper(mPreferencesHelper);
3813         when(mCompanionMgr.getAssociations(PKG, mUserId))
3814                 .thenReturn(singletonList(mock(AssociationInfo.class)));
3815 
3816         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
3817                 null, PKG, Process.myUserHandle());
3818 
3819         verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
3820     }
3821 
3822     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_noAccess()3823     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
3824         mService.setPreferencesHelper(mPreferencesHelper);
3825         when(mCompanionMgr.getAssociations(PKG, mUserId))
3826                 .thenReturn(emptyList());
3827 
3828         try {
3829             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
3830                     null, PKG, Process.myUserHandle());
3831             fail("listeners that don't have a companion device shouldn't be able to call this");
3832         } catch (SecurityException e) {
3833             // pass
3834         }
3835 
3836         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
3837     }
3838 
3839     @Test
testGetNotificationChannelGroupsFromPrivilegedListener_badUser()3840     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
3841         mService.setPreferencesHelper(mPreferencesHelper);
3842         when(mCompanionMgr.getAssociations(PKG, mUserId))
3843                 .thenReturn(emptyList());
3844         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3845         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3846         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3847         try {
3848             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
3849                     null, PKG, Process.myUserHandle());
3850             fail("listeners that don't have a companion device shouldn't be able to call this");
3851         } catch (SecurityException e) {
3852             // pass
3853         }
3854 
3855         verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
3856     }
3857 
3858     @Test
testHasCompanionDevice_failure()3859     public void testHasCompanionDevice_failure() throws Exception {
3860         when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
3861                 new IllegalArgumentException());
3862         mService.hasCompanionDevice(mListener);
3863     }
3864 
3865     @Test
testHasCompanionDevice_noService()3866     public void testHasCompanionDevice_noService() {
3867         NotificationManagerService noManService =
3868                 new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
3869                 mNotificationInstanceIdSequence);
3870 
3871         assertFalse(noManService.hasCompanionDevice(mListener));
3872     }
3873 
3874     @Test
testCrossUserSnooze()3875     public void testCrossUserSnooze() {
3876         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10);
3877         mService.addNotification(r);
3878         NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0);
3879         mService.addNotification(r2);
3880 
3881         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3882         mListener.component = new ComponentName(PKG, PKG);
3883         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
3884         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3885 
3886         mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener);
3887 
3888         verify(mWorkerHandler, never()).post(
3889                 any(NotificationManagerService.SnoozeNotificationRunnable.class));
3890     }
3891 
3892     @Test
testSameUserSnooze()3893     public void testSameUserSnooze() {
3894         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10);
3895         mService.addNotification(r);
3896         NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0);
3897         mService.addNotification(r2);
3898 
3899         mListener = mock(ManagedServices.ManagedServiceInfo.class);
3900         mListener.component = new ComponentName(PKG, PKG);
3901         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(true);
3902         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
3903 
3904         mService.snoozeNotificationInt(r2.getKey(), 1000, null, mListener);
3905 
3906         verify(mWorkerHandler).post(
3907                 any(NotificationManagerService.SnoozeNotificationRunnable.class));
3908     }
3909 
3910     @Test
testSnoozeRunnable_tooManySnoozed_singleNotification()3911     public void testSnoozeRunnable_tooManySnoozed_singleNotification() {
3912         final NotificationRecord notification = generateNotificationRecord(
3913                 mTestNotificationChannel, 1, null, true);
3914         mService.addNotification(notification);
3915 
3916         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
3917         when(mSnoozeHelper.canSnooze(1)).thenReturn(false);
3918 
3919         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
3920                 mService.new SnoozeNotificationRunnable(
3921                         notification.getKey(), 100, null);
3922         snoozeNotificationRunnable.run();
3923 
3924         verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
3925         assertThat(mService.getNotificationRecordCount()).isEqualTo(1);
3926     }
3927 
3928     @Test
testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification()3929     public void testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification() {
3930         final NotificationRecord notification = generateNotificationRecord(
3931                 mTestNotificationChannel, 1, "group", true);
3932         final NotificationRecord notificationChild = generateNotificationRecord(
3933                 mTestNotificationChannel, 1, "group", false);
3934         mService.addNotification(notification);
3935         mService.addNotification(notificationChild);
3936 
3937         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
3938         when(mSnoozeHelper.canSnooze(2)).thenReturn(false);
3939 
3940         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
3941                 mService.new SnoozeNotificationRunnable(
3942                         notificationChild.getKey(), 100, null);
3943         snoozeNotificationRunnable.run();
3944 
3945         verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
3946         assertThat(mService.getNotificationRecordCount()).isEqualTo(2);
3947     }
3948 
3949     @Test
testSnoozeRunnable_tooManySnoozed_summaryNotification()3950     public void testSnoozeRunnable_tooManySnoozed_summaryNotification() {
3951         final NotificationRecord notification = generateNotificationRecord(
3952                 mTestNotificationChannel, 1, "group", true);
3953         final NotificationRecord notificationChild = generateNotificationRecord(
3954                 mTestNotificationChannel, 12, "group", false);
3955         final NotificationRecord notificationChild2 = generateNotificationRecord(
3956                 mTestNotificationChannel, 13, "group", false);
3957         mService.addNotification(notification);
3958         mService.addNotification(notificationChild);
3959         mService.addNotification(notificationChild2);
3960 
3961         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
3962         when(mSnoozeHelper.canSnooze(3)).thenReturn(false);
3963 
3964         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
3965                 mService.new SnoozeNotificationRunnable(
3966                         notification.getKey(), 100, null);
3967         snoozeNotificationRunnable.run();
3968 
3969         verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
3970         assertThat(mService.getNotificationRecordCount()).isEqualTo(3);
3971     }
3972 
3973     @Test
testSnoozeRunnable_reSnoozeASingleSnoozedNotification()3974     public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() {
3975         final NotificationRecord notification = generateNotificationRecord(
3976                 mTestNotificationChannel, 1, null, true);
3977         mService.addNotification(notification);
3978         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
3979         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
3980 
3981         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
3982                 mService.new SnoozeNotificationRunnable(
3983                 notification.getKey(), 100, null);
3984         snoozeNotificationRunnable.run();
3985         snoozeNotificationRunnable.run();
3986 
3987         // snooze twice
3988         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
3989     }
3990 
3991     @Test
testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey()3992     public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() {
3993         final NotificationRecord notification = generateNotificationRecord(
3994                 mTestNotificationChannel, 1, "group", true);
3995         mService.addNotification(notification);
3996         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
3997         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
3998 
3999         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4000                 mService.new SnoozeNotificationRunnable(
4001                 notification.getKey(), 100, null);
4002         snoozeNotificationRunnable.run();
4003         snoozeNotificationRunnable.run();
4004 
4005         // snooze twice
4006         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
4007     }
4008 
4009     @Test
testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey()4010     public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
4011         final NotificationRecord notification = generateNotificationRecord(
4012                 mTestNotificationChannel, 1, "group", true);
4013         final NotificationRecord notification2 = generateNotificationRecord(
4014                 mTestNotificationChannel, 2, "group", true);
4015         mService.addNotification(notification);
4016         mService.addNotification(notification2);
4017         when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
4018         when(mSnoozeHelper.getNotifications(
4019                 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
4020         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4021 
4022         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4023                 mService.new SnoozeNotificationRunnable(
4024                         notification.getKey(), 100, null);
4025         snoozeNotificationRunnable.run();
4026         when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
4027                 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
4028         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
4029                 mService.new SnoozeNotificationRunnable(
4030                         notification2.getKey(), 100, null);
4031         snoozeNotificationRunnable2.run();
4032 
4033         // snooze twice
4034         verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
4035     }
4036 
4037     @Test
testSnoozeRunnable_snoozeNonGrouped()4038     public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
4039         final NotificationRecord nonGrouped = generateNotificationRecord(
4040                 mTestNotificationChannel, 1, null, false);
4041         final NotificationRecord grouped = generateNotificationRecord(
4042                 mTestNotificationChannel, 2, "group", false);
4043         mService.addNotification(grouped);
4044         mService.addNotification(nonGrouped);
4045         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4046 
4047         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4048                 mService.new SnoozeNotificationRunnable(
4049                         nonGrouped.getKey(), 100, null);
4050         snoozeNotificationRunnable.run();
4051 
4052         // only snooze the one notification
4053         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4054         assertTrue(nonGrouped.getStats().hasSnoozed());
4055 
4056         assertEquals(2, mNotificationRecordLogger.numCalls());
4057         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4058                 mNotificationRecordLogger.event(0));
4059         assertEquals(
4060                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4061                 mNotificationRecordLogger.event(1));
4062     }
4063 
4064     @Test
testSnoozeRunnable_snoozeSummary_withChildren()4065     public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
4066         final NotificationRecord parent = generateNotificationRecord(
4067                 mTestNotificationChannel, 1, "group", true);
4068         final NotificationRecord child = generateNotificationRecord(
4069                 mTestNotificationChannel, 2, "group", false);
4070         final NotificationRecord child2 = generateNotificationRecord(
4071                 mTestNotificationChannel, 3, "group", false);
4072         mService.addNotification(parent);
4073         mService.addNotification(child);
4074         mService.addNotification(child2);
4075         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4076 
4077         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4078                 mService.new SnoozeNotificationRunnable(
4079                         parent.getKey(), 100, null);
4080         snoozeNotificationRunnable.run();
4081 
4082         // snooze parent and children
4083         verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
4084     }
4085 
4086     @Test
testSnoozeRunnable_snoozeGroupChild_fellowChildren()4087     public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
4088         final NotificationRecord parent = generateNotificationRecord(
4089                 mTestNotificationChannel, 1, "group", true);
4090         final NotificationRecord child = generateNotificationRecord(
4091                 mTestNotificationChannel, 2, "group", false);
4092         final NotificationRecord child2 = generateNotificationRecord(
4093                 mTestNotificationChannel, 3, "group", false);
4094         mService.addNotification(parent);
4095         mService.addNotification(child);
4096         mService.addNotification(child2);
4097         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4098 
4099         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4100                 mService.new SnoozeNotificationRunnable(
4101                         child2.getKey(), 100, null);
4102         snoozeNotificationRunnable.run();
4103 
4104         // only snooze the one child
4105         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4106 
4107         assertEquals(2, mNotificationRecordLogger.numCalls());
4108         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4109                 mNotificationRecordLogger.event(0));
4110         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
4111                         .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
4112     }
4113 
4114     @Test
testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary()4115     public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
4116         final NotificationRecord parent = generateNotificationRecord(
4117                 mTestNotificationChannel, 1, "group", true);
4118         assertTrue(parent.getSbn().getNotification().isGroupSummary());
4119         final NotificationRecord child = generateNotificationRecord(
4120                 mTestNotificationChannel, 2, "group", false);
4121         mService.addNotification(parent);
4122         mService.addNotification(child);
4123         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4124 
4125         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4126                 mService.new SnoozeNotificationRunnable(
4127                         child.getKey(), 100, null);
4128         snoozeNotificationRunnable.run();
4129 
4130         // snooze child and summary
4131         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
4132 
4133         assertEquals(4, mNotificationRecordLogger.numCalls());
4134         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4135                 mNotificationRecordLogger.event(0));
4136         assertEquals(
4137                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4138                 mNotificationRecordLogger.event(1));
4139         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4140                 mNotificationRecordLogger.event(2));
4141         assertEquals(
4142                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4143                 mNotificationRecordLogger.event(3));
4144     }
4145 
4146     @Test
testSnoozeRunnable_snoozeGroupChild_noOthersInGroup()4147     public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
4148         final NotificationRecord child = generateNotificationRecord(
4149                 mTestNotificationChannel, 2, "group", false);
4150         mService.addNotification(child);
4151         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4152 
4153         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4154                 mService.new SnoozeNotificationRunnable(
4155                         child.getKey(), 100, null);
4156         snoozeNotificationRunnable.run();
4157 
4158         // snooze child only
4159         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4160 
4161         assertEquals(2, mNotificationRecordLogger.numCalls());
4162         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4163                 mNotificationRecordLogger.event(0));
4164         assertEquals(
4165                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4166                 mNotificationRecordLogger.event(1));
4167     }
4168 
4169     @Test
testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed()4170     public void testSnoozeRunnable_snoozeAutoGroupChild_summaryNotSnoozed() throws Exception {
4171         final NotificationRecord parent = generateNotificationRecord(
4172                 mTestNotificationChannel, 1, GroupHelper.AUTOGROUP_KEY, true);
4173         final NotificationRecord child = generateNotificationRecord(
4174                 mTestNotificationChannel, 2, GroupHelper.AUTOGROUP_KEY, false);
4175         mService.addNotification(parent);
4176         mService.addNotification(child);
4177         when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
4178 
4179         // snooze child only
4180         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4181                 mService.new SnoozeNotificationRunnable(
4182                         child.getKey(), 100, null);
4183         snoozeNotificationRunnable.run();
4184 
4185         // only child should be snoozed
4186         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
4187 
4188         // both group summary and child should be cancelled
4189         assertNull(mService.getNotificationRecord(parent.getKey()));
4190         assertNull(mService.getNotificationRecord(child.getKey()));
4191 
4192         assertEquals(4, mNotificationRecordLogger.numCalls());
4193         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
4194                 mNotificationRecordLogger.event(0));
4195         assertEquals(
4196                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
4197                 mNotificationRecordLogger.event(1));
4198     }
4199 
4200     @Test
testPostGroupChild_unsnoozeParent()4201     public void testPostGroupChild_unsnoozeParent() throws Exception {
4202         final NotificationRecord child = generateNotificationRecord(
4203                 mTestNotificationChannel, 2, "group", false);
4204 
4205         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
4206                 child.getSbn().getId(), child.getSbn().getNotification(),
4207                 child.getSbn().getUserId());
4208         waitForIdle();
4209 
4210         verify(mSnoozeHelper, times(1)).repostGroupSummary(
4211                 anyString(), anyInt(), eq(child.getGroupKey()));
4212     }
4213 
4214     @Test
testPostNonGroup_noUnsnoozing()4215     public void testPostNonGroup_noUnsnoozing() throws Exception {
4216         final NotificationRecord record = generateNotificationRecord(
4217                 mTestNotificationChannel, 2, null, false);
4218 
4219         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
4220                 record.getSbn().getId(), record.getSbn().getNotification(),
4221                 record.getSbn().getUserId());
4222         waitForIdle();
4223 
4224         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
4225     }
4226 
4227     @Test
testPostGroupSummary_noUnsnoozing()4228     public void testPostGroupSummary_noUnsnoozing() throws Exception {
4229         final NotificationRecord parent = generateNotificationRecord(
4230                 mTestNotificationChannel, 2, "group", true);
4231 
4232         mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
4233                 parent.getSbn().getId(), parent.getSbn().getNotification(),
4234                 parent.getSbn().getUserId());
4235         waitForIdle();
4236 
4237         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
4238     }
4239 
4240     @Test
testSystemNotificationListenerCanUnsnooze()4241     public void testSystemNotificationListenerCanUnsnooze() throws Exception {
4242         final NotificationRecord nr = generateNotificationRecord(
4243                 mTestNotificationChannel, 2, "group", false);
4244 
4245         mBinderService.enqueueNotificationWithTag(PKG, PKG,
4246                 "testSystemNotificationListenerCanUnsnooze",
4247                 nr.getSbn().getId(), nr.getSbn().getNotification(),
4248                 nr.getSbn().getUserId());
4249         waitForIdle();
4250         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
4251                 mService.new SnoozeNotificationRunnable(
4252                         nr.getKey(), 100, null);
4253         snoozeNotificationRunnable.run();
4254 
4255         ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
4256                 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0, 234);
4257         listener.isSystem = true;
4258         when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
4259 
4260         mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
4261         waitForIdle();
4262         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4263         assertEquals(1, notifs.length);
4264         assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
4265     }
4266 
4267     @Test
testSetListenerAccessForUser()4268     public void testSetListenerAccessForUser() throws Exception {
4269         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4270         ComponentName c = ComponentName.unflattenFromString("package/Component");
4271         mBinderService.setNotificationListenerAccessGrantedForUser(
4272                 c, user.getIdentifier(), true, true);
4273 
4274 
4275         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
4276         verify(mListeners, times(1)).setPackageOrComponentEnabled(
4277                 c.flattenToString(), user.getIdentifier(), true, true, true);
4278         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4279                 c.flattenToString(), user.getIdentifier(), false, true, true);
4280         verify(mAssistants, never()).setPackageOrComponentEnabled(
4281                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4282     }
4283 
4284     @Test
testSetListenerAccessForUser_grantWithNameTooLong_throws()4285     public void testSetListenerAccessForUser_grantWithNameTooLong_throws() {
4286         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4287         ComponentName c = new ComponentName("com.example.package",
4288                 com.google.common.base.Strings.repeat("Blah", 150));
4289 
4290         assertThrows(IllegalArgumentException.class,
4291                 () -> mBinderService.setNotificationListenerAccessGrantedForUser(
4292                         c, user.getIdentifier(), /* enabled= */ true, true));
4293     }
4294 
4295     @Test
testSetListenerAccessForUser_revokeWithNameTooLong_okay()4296     public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception {
4297         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4298         ComponentName c = new ComponentName("com.example.package",
4299                 com.google.common.base.Strings.repeat("Blah", 150));
4300 
4301         mBinderService.setNotificationListenerAccessGrantedForUser(
4302                 c, user.getIdentifier(), /* enabled= */ false, true);
4303 
4304         verify(mListeners).setPackageOrComponentEnabled(
4305                 c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true);
4306     }
4307 
4308     @Test
testSetAssistantAccessForUser()4309     public void testSetAssistantAccessForUser() throws Exception {
4310         UserInfo ui = new UserInfo();
4311         ui.id = mContext.getUserId() + 10;
4312         UserHandle user = UserHandle.of(ui.id);
4313         List<UserInfo> uis = new ArrayList<>();
4314         uis.add(ui);
4315         ComponentName c = ComponentName.unflattenFromString("package/Component");
4316         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4317 
4318         mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
4319 
4320         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
4321         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4322                 c.flattenToString(), user.getIdentifier(), true, true, true);
4323         verify(mAssistants).setUserSet(ui.id, true);
4324         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4325                 c.flattenToString(), user.getIdentifier(), false, true);
4326         verify(mListeners, never()).setPackageOrComponentEnabled(
4327                 any(), anyInt(), anyBoolean(), anyBoolean());
4328     }
4329 
4330     @Test
testGetAssistantAllowedForUser()4331     public void testGetAssistantAllowedForUser() throws Exception {
4332         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4333         try {
4334             mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
4335         } catch (IllegalStateException e) {
4336             if (!e.getMessage().contains("At most one NotificationAssistant")) {
4337                 throw e;
4338             }
4339         }
4340         verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
4341     }
4342 
4343     @Test
testGetAssistantAllowed()4344     public void testGetAssistantAllowed() throws Exception {
4345         try {
4346             mBinderService.getAllowedNotificationAssistant();
4347         } catch (IllegalStateException e) {
4348             if (!e.getMessage().contains("At most one NotificationAssistant")) {
4349                 throw e;
4350             }
4351         }
4352         verify(mAssistants, times(1)).getAllowedComponents(mContext.getUserId());
4353     }
4354 
4355     @Test
testSetNASMigrationDoneAndResetDefault_enableNAS()4356     public void testSetNASMigrationDoneAndResetDefault_enableNAS() throws Exception {
4357         int userId = 10;
4358         setNASMigrationDone(false, userId);
4359         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
4360 
4361         mBinderService.setNASMigrationDoneAndResetDefault(userId, true);
4362 
4363         assertTrue(mService.isNASMigrationDone(userId));
4364         verify(mAssistants, times(1)).resetDefaultFromConfig();
4365     }
4366 
4367     @Test
testSetNASMigrationDoneAndResetDefault_disableNAS()4368     public void testSetNASMigrationDoneAndResetDefault_disableNAS() throws Exception {
4369         int userId = 10;
4370         setNASMigrationDone(false, userId);
4371         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
4372 
4373         mBinderService.setNASMigrationDoneAndResetDefault(userId, false);
4374 
4375         assertTrue(mService.isNASMigrationDone(userId));
4376         verify(mAssistants, times(1)).clearDefaults();
4377     }
4378 
4379     @Test
testSetNASMigrationDoneAndResetDefault_multiProfile()4380     public void testSetNASMigrationDoneAndResetDefault_multiProfile() throws Exception {
4381         int userId1 = 11;
4382         int userId2 = 12; //work profile
4383         setNASMigrationDone(false, userId1);
4384         setNASMigrationDone(false, userId2);
4385         setUsers(new int[]{userId1, userId2});
4386         when(mUm.isManagedProfile(userId2)).thenReturn(true);
4387         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2});
4388 
4389         mBinderService.setNASMigrationDoneAndResetDefault(userId1, true);
4390         assertTrue(mService.isNASMigrationDone(userId1));
4391         assertTrue(mService.isNASMigrationDone(userId2));
4392     }
4393 
4394     @Test
testSetNASMigrationDoneAndResetDefault_multiUser()4395     public void testSetNASMigrationDoneAndResetDefault_multiUser() throws Exception {
4396         int userId1 = 11;
4397         int userId2 = 12;
4398         setNASMigrationDone(false, userId1);
4399         setNASMigrationDone(false, userId2);
4400         setUsers(new int[]{userId1, userId2});
4401         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1});
4402         when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2});
4403 
4404         mBinderService.setNASMigrationDoneAndResetDefault(userId1, true);
4405         assertTrue(mService.isNASMigrationDone(userId1));
4406         assertFalse(mService.isNASMigrationDone(userId2));
4407     }
4408 
4409     @Test
testSetDndAccessForUser()4410     public void testSetDndAccessForUser() throws Exception {
4411         UserHandle user = UserHandle.of(mContext.getUserId() + 10);
4412         ComponentName c = ComponentName.unflattenFromString("package/Component");
4413         mBinderService.setNotificationPolicyAccessGrantedForUser(
4414                 c.getPackageName(), user.getIdentifier(), true);
4415 
4416         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
4417         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4418                 c.getPackageName(), user.getIdentifier(), true, true);
4419         verify(mAssistants, never()).setPackageOrComponentEnabled(
4420                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4421         verify(mListeners, never()).setPackageOrComponentEnabled(
4422                 any(), anyInt(), anyBoolean(), anyBoolean());
4423     }
4424 
4425     @Test
testSetListenerAccess()4426     public void testSetListenerAccess() throws Exception {
4427         ComponentName c = ComponentName.unflattenFromString("package/Component");
4428         mBinderService.setNotificationListenerAccessGranted(c, true, true);
4429 
4430         verify(mListeners, times(1)).setPackageOrComponentEnabled(
4431                 c.flattenToString(), mContext.getUserId(), true, true, true);
4432         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4433                 c.flattenToString(), mContext.getUserId(), false, true, true);
4434         verify(mAssistants, never()).setPackageOrComponentEnabled(
4435                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4436     }
4437 
4438     @Test
testSetAssistantAccess()4439     public void testSetAssistantAccess() throws Exception {
4440         List<UserInfo> uis = new ArrayList<>();
4441         UserInfo ui = new UserInfo();
4442         ui.id = mContext.getUserId();
4443         uis.add(ui);
4444         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4445         ComponentName c = ComponentName.unflattenFromString("package/Component");
4446 
4447         mBinderService.setNotificationAssistantAccessGranted(c, true);
4448 
4449         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4450                 c.flattenToString(), ui.id, true, true, true);
4451         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4452                 c.flattenToString(), ui.id, false, true);
4453         verify(mListeners, never()).setPackageOrComponentEnabled(
4454                 any(), anyInt(), anyBoolean(), anyBoolean());
4455     }
4456 
4457     @Test
testSetAssistantAccess_multiProfile()4458     public void testSetAssistantAccess_multiProfile() throws Exception {
4459         List<UserInfo> uis = new ArrayList<>();
4460         UserInfo ui = new UserInfo();
4461         ui.id = mContext.getUserId();
4462         uis.add(ui);
4463         UserInfo ui10 = new UserInfo();
4464         ui10.id = mContext.getUserId() + 10;
4465         uis.add(ui10);
4466         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4467         ComponentName c = ComponentName.unflattenFromString("package/Component");
4468 
4469         mBinderService.setNotificationAssistantAccessGranted(c, true);
4470 
4471         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4472                 c.flattenToString(), ui.id, true, true, true);
4473         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4474                 c.flattenToString(), ui10.id, true, true, true);
4475 
4476         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4477                 c.flattenToString(), ui.id, false, true);
4478         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4479                 c.flattenToString(), ui10.id, false, true);
4480         verify(mListeners, never()).setPackageOrComponentEnabled(
4481                 any(), anyInt(), anyBoolean(), anyBoolean());
4482     }
4483 
4484     @Test
testSetAssistantAccess_nullWithAllowedAssistant()4485     public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
4486         ArrayList<ComponentName> componentList = new ArrayList<>();
4487         ComponentName c = ComponentName.unflattenFromString("package/Component");
4488         componentList.add(c);
4489         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
4490         List<UserInfo> uis = new ArrayList<>();
4491         UserInfo ui = new UserInfo();
4492         ui.id = mContext.getUserId();
4493         uis.add(ui);
4494         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4495 
4496         mBinderService.setNotificationAssistantAccessGranted(null, true);
4497 
4498         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4499                 c.flattenToString(), ui.id, true, false, true);
4500         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4501                 c.flattenToString(), ui.id, false,  false);
4502         verify(mListeners, never()).setPackageOrComponentEnabled(
4503                 any(), anyInt(), anyBoolean(), anyBoolean());
4504     }
4505 
4506     @Test
testSetAssistantAccessForUser_nullWithAllowedAssistant()4507     public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
4508         List<UserInfo> uis = new ArrayList<>();
4509         UserInfo ui = new UserInfo();
4510         ui.id = mContext.getUserId() + 10;
4511         uis.add(ui);
4512         UserHandle user = ui.getUserHandle();
4513         ArrayList<ComponentName> componentList = new ArrayList<>();
4514         ComponentName c = ComponentName.unflattenFromString("package/Component");
4515         componentList.add(c);
4516         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
4517         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4518 
4519         mBinderService.setNotificationAssistantAccessGrantedForUser(
4520                 null, user.getIdentifier(), true);
4521 
4522         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4523                 c.flattenToString(), user.getIdentifier(), true, false, true);
4524         verify(mAssistants).setUserSet(ui.id, true);
4525         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4526                 c.flattenToString(), user.getIdentifier(), false,  false);
4527         verify(mListeners, never()).setPackageOrComponentEnabled(
4528                 any(), anyInt(), anyBoolean(), anyBoolean());
4529     }
4530 
4531     @Test
testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()4532     public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
4533             throws Exception {
4534         List<UserInfo> uis = new ArrayList<>();
4535         UserInfo ui = new UserInfo();
4536         ui.id = mContext.getUserId();
4537         uis.add(ui);
4538         UserInfo ui10 = new UserInfo();
4539         ui10.id = mContext.getUserId() + 10;
4540         uis.add(ui10);
4541         UserHandle user = ui.getUserHandle();
4542         ArrayList<ComponentName> componentList = new ArrayList<>();
4543         ComponentName c = ComponentName.unflattenFromString("package/Component");
4544         componentList.add(c);
4545         when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
4546         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4547 
4548         mBinderService.setNotificationAssistantAccessGrantedForUser(
4549                     null, user.getIdentifier(), true);
4550 
4551         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4552                 c.flattenToString(), user.getIdentifier(), true, false, true);
4553         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4554                 c.flattenToString(), ui10.id, true, false, true);
4555         verify(mAssistants).setUserSet(ui.id, true);
4556         verify(mAssistants).setUserSet(ui10.id, true);
4557         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4558                 c.flattenToString(), user.getIdentifier(), false,  false);
4559         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4560                 c.flattenToString(), ui10.id, false,  false);
4561         verify(mListeners, never()).setPackageOrComponentEnabled(
4562                 any(), anyInt(), anyBoolean(), anyBoolean());
4563     }
4564 
4565     @Test
testSetDndAccess()4566     public void testSetDndAccess() throws Exception {
4567         ComponentName c = ComponentName.unflattenFromString("package/Component");
4568 
4569         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
4570 
4571         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4572                 c.getPackageName(), mContext.getUserId(), true, true);
4573         verify(mAssistants, never()).setPackageOrComponentEnabled(
4574                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4575         verify(mListeners, never()).setPackageOrComponentEnabled(
4576                 any(), anyInt(), anyBoolean(), anyBoolean());
4577     }
4578 
4579     @Test
testSetListenerAccess_onLowRam()4580     public void testSetListenerAccess_onLowRam() throws Exception {
4581         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4582         ComponentName c = ComponentName.unflattenFromString("package/Component");
4583         mBinderService.setNotificationListenerAccessGranted(c, true, true);
4584 
4585         verify(mListeners).setPackageOrComponentEnabled(
4586                 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4587         verify(mConditionProviders).setPackageOrComponentEnabled(
4588                 anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4589         verify(mAssistants).migrateToXml();
4590         verify(mAssistants).resetDefaultAssistantsIfNecessary();
4591     }
4592 
4593     @Test
testSetAssistantAccess_onLowRam()4594     public void testSetAssistantAccess_onLowRam() throws Exception {
4595         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4596         ComponentName c = ComponentName.unflattenFromString("package/Component");
4597         List<UserInfo> uis = new ArrayList<>();
4598         UserInfo ui = new UserInfo();
4599         ui.id = mContext.getUserId();
4600         uis.add(ui);
4601         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4602 
4603         mBinderService.setNotificationAssistantAccessGranted(c, true);
4604 
4605         verify(mListeners).migrateToXml();
4606         verify(mConditionProviders).setPackageOrComponentEnabled(
4607                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4608         verify(mAssistants).migrateToXml();
4609         verify(mAssistants).resetDefaultAssistantsIfNecessary();
4610     }
4611 
4612     @Test
testSetDndAccess_onLowRam()4613     public void testSetDndAccess_onLowRam() throws Exception {
4614         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4615         ComponentName c = ComponentName.unflattenFromString("package/Component");
4616         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
4617 
4618         verify(mListeners).migrateToXml();
4619         verify(mConditionProviders).setPackageOrComponentEnabled(
4620                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4621         verify(mAssistants).migrateToXml();
4622         verify(mAssistants).resetDefaultAssistantsIfNecessary();
4623     }
4624 
4625     @Test
testSetListenerAccess_doesNothingOnLowRam_exceptWatch()4626     public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
4627         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4628         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4629         ComponentName c = ComponentName.unflattenFromString("package/Component");
4630 
4631         mBinderService.setNotificationListenerAccessGranted(c, true, true);
4632 
4633         verify(mListeners, times(1)).setPackageOrComponentEnabled(
4634                 c.flattenToString(), mContext.getUserId(), true, true, true);
4635         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4636                 c.flattenToString(), mContext.getUserId(), false, true, true);
4637         verify(mAssistants, never()).setPackageOrComponentEnabled(
4638                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4639     }
4640 
4641     @Test
testSetAssistantAccess_doesNothingOnLowRam_exceptWatch()4642     public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
4643         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4644         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4645         ComponentName c = ComponentName.unflattenFromString("package/Component");
4646         List<UserInfo> uis = new ArrayList<>();
4647         UserInfo ui = new UserInfo();
4648         ui.id = mContext.getUserId();
4649         uis.add(ui);
4650         when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
4651 
4652         mBinderService.setNotificationAssistantAccessGranted(c, true);
4653 
4654         verify(mListeners, never()).setPackageOrComponentEnabled(
4655                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4656         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4657                 c.flattenToString(), ui.id, false, true);
4658         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
4659                 c.flattenToString(), ui.id, true, true, true);
4660     }
4661 
4662     @Test
testSetDndAccess_doesNothingOnLowRam_exceptWatch()4663     public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
4664         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4665         when(mActivityManager.isLowRamDevice()).thenReturn(true);
4666         ComponentName c = ComponentName.unflattenFromString("package/Component");
4667 
4668         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
4669 
4670         verify(mListeners, never()).setPackageOrComponentEnabled(
4671                 anyString(), anyInt(), anyBoolean(), anyBoolean());
4672         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4673                 c.getPackageName(), mContext.getUserId(), true, true);
4674         verify(mAssistants, never()).setPackageOrComponentEnabled(
4675                 any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
4676     }
4677 
4678     @Test
testOnlyAutogroupIfNeeded_newNotification_ghUpdate()4679     public void testOnlyAutogroupIfNeeded_newNotification_ghUpdate() {
4680         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
4681         mService.addEnqueuedNotification(r);
4682         NotificationManagerService.PostNotificationRunnable runnable =
4683                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
4684                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4685         runnable.run();
4686         waitForIdle();
4687 
4688         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
4689     }
4690 
4691     @Test
testOnlyAutogroupIfNeeded_groupChanged_ghUpdate()4692     public void testOnlyAutogroupIfNeeded_groupChanged_ghUpdate() {
4693         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0,
4694                 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", "group", false);
4695         mService.addNotification(r);
4696 
4697         NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0,
4698                 "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", null, false);
4699         mService.addEnqueuedNotification(update);
4700         NotificationManagerService.PostNotificationRunnable runnable =
4701                 mService.new PostNotificationRunnable(update.getKey(),
4702                         update.getSbn().getPackageName(), update.getUid(),
4703                         mPostNotificationTrackerFactory.newTracker(null));
4704         runnable.run();
4705         waitForIdle();
4706 
4707         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
4708     }
4709 
4710     @Test
testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate()4711     public void testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate() {
4712         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0,
4713                 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", "group", false);
4714         mService.addNotification(r);
4715 
4716         NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0,
4717                 "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", null, false);
4718         update.getNotification().flags = FLAG_AUTO_CANCEL;
4719         mService.addEnqueuedNotification(update);
4720         NotificationManagerService.PostNotificationRunnable runnable =
4721                 mService.new PostNotificationRunnable(update.getKey(),
4722                         update.getSbn().getPackageName(), update.getUid(),
4723                         mPostNotificationTrackerFactory.newTracker(null));
4724         runnable.run();
4725         waitForIdle();
4726 
4727         verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
4728     }
4729 
4730     @Test
testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate()4731     public void testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate() {
4732         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0,
4733                 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false);
4734         mService.addNotification(r);
4735         NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0,
4736                 "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false);
4737         update.getNotification().color = Color.BLACK;
4738         mService.addEnqueuedNotification(update);
4739 
4740         NotificationManagerService.PostNotificationRunnable runnable =
4741                 mService.new PostNotificationRunnable(update.getKey(),
4742                         update.getSbn().getPackageName(),
4743                         update.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4744         runnable.run();
4745         waitForIdle();
4746 
4747         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
4748     }
4749 
4750     @Test
testDontAutogroupIfCritical()4751     public void testDontAutogroupIfCritical() throws Exception {
4752         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
4753         r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
4754         mService.addEnqueuedNotification(r);
4755         NotificationManagerService.PostNotificationRunnable runnable =
4756                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
4757                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4758         runnable.run();
4759 
4760         r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
4761         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
4762         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
4763                 r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
4764         mService.addEnqueuedNotification(r);
4765 
4766         runnable.run();
4767         waitForIdle();
4768 
4769         verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
4770     }
4771 
4772     @Test
testNoNotificationDuringSetupPermission()4773     public void testNoNotificationDuringSetupPermission() throws Exception {
4774         mContext.getTestablePermissions().setPermission(
4775                 android.Manifest.permission.NOTIFICATION_DURING_SETUP, PERMISSION_GRANTED);
4776         Bundle extras = new Bundle();
4777         extras.putBoolean(EXTRA_ALLOW_DURING_SETUP, true);
4778         Notification.Builder nb = new Notification.Builder(mContext,
4779                 mTestNotificationChannel.getId())
4780                 .setContentTitle("foo")
4781                 .addExtras(extras)
4782                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4783         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4784                 "testNoNotificationDuringSetupPermission", mUid, 0,
4785                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4786         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4787 
4788         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4789                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4790         waitForIdle();
4791 
4792         NotificationRecord posted = mService.findNotificationLocked(
4793                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4794 
4795         assertTrue(posted.getNotification().extras.containsKey(EXTRA_ALLOW_DURING_SETUP));
4796     }
4797 
4798     @Test
testNoFakeColorizedPermission()4799     public void testNoFakeColorizedPermission() throws Exception {
4800         mContext.getTestablePermissions().setPermission(
4801                 android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_DENIED);
4802         Notification.Builder nb = new Notification.Builder(mContext,
4803                 mTestNotificationChannel.getId())
4804                 .setContentTitle("foo")
4805                 .setColorized(true).setColor(Color.WHITE)
4806                 .setFlag(FLAG_CAN_COLORIZE, true)
4807                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4808         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4809                 "testNoFakeColorizedPermission", mUid, 0,
4810                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4811         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4812 
4813         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4814                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4815         waitForIdle();
4816 
4817         NotificationRecord posted = mService.findNotificationLocked(
4818                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4819 
4820         assertFalse(posted.getNotification().isColorized());
4821     }
4822 
4823     @Test
testMediaStyleRemote_hasPermission()4824     public void testMediaStyleRemote_hasPermission() throws RemoteException {
4825         String deviceName = "device";
4826         mContext.getTestablePermissions().setPermission(
4827                 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_GRANTED);
4828         Notification.MediaStyle style = new Notification.MediaStyle();
4829         style.setRemotePlaybackInfo(deviceName, 0, null);
4830         Notification.Builder nb = new Notification.Builder(mContext,
4831                 mTestNotificationChannel.getId())
4832                 .setStyle(style);
4833 
4834         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4835                 "testMediaStyleRemoteHasPermission", mUid, 0,
4836                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4837         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4838 
4839         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4840                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4841         waitForIdle();
4842 
4843         NotificationRecord posted = mService.findNotificationLocked(
4844                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4845         Bundle extras = posted.getNotification().extras;
4846 
4847         assertTrue(extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4848         assertEquals(deviceName, extras.getString(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4849     }
4850 
4851     @Test
testMediaStyleRemote_noPermission()4852     public void testMediaStyleRemote_noPermission() throws RemoteException {
4853         String deviceName = "device";
4854         mContext.getTestablePermissions().setPermission(
4855                 android.Manifest.permission.MEDIA_CONTENT_CONTROL, PERMISSION_DENIED);
4856         Notification.MediaStyle style = new Notification.MediaStyle();
4857         style.setRemotePlaybackInfo(deviceName, 0, null);
4858         Notification.Builder nb = new Notification.Builder(mContext,
4859                 mTestNotificationChannel.getId())
4860                 .setStyle(style);
4861 
4862         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4863                 "testMediaStyleRemoteNoPermission", mUid, 0,
4864                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4865         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4866 
4867         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4868                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4869         waitForIdle();
4870 
4871         NotificationRecord posted = mService.findNotificationLocked(
4872                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4873 
4874         assertFalse(posted.getNotification().extras
4875                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4876         assertFalse(posted.getNotification().extras
4877                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON));
4878         assertFalse(posted.getNotification().extras
4879                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT));
4880     }
4881 
4882     @Test
testCustomMediaStyleRemote_noPermission()4883     public void testCustomMediaStyleRemote_noPermission() throws RemoteException {
4884         String deviceName = "device";
4885         when(mPackageManager.checkPermission(
4886                 eq(android.Manifest.permission.MEDIA_CONTENT_CONTROL), any(), anyInt()))
4887                 .thenReturn(PERMISSION_DENIED);
4888         Notification.DecoratedMediaCustomViewStyle style =
4889                 new Notification.DecoratedMediaCustomViewStyle();
4890         style.setRemotePlaybackInfo(deviceName, 0, null);
4891         Notification.Builder nb = new Notification.Builder(mContext,
4892                 mTestNotificationChannel.getId())
4893                 .setStyle(style);
4894 
4895         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4896                 "testCustomMediaStyleRemoteNoPermission", mUid, 0,
4897                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4898         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4899 
4900         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4901                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4902         waitForIdle();
4903 
4904         NotificationRecord posted = mService.findNotificationLocked(
4905                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4906 
4907         assertFalse(posted.getNotification().extras
4908                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
4909         assertFalse(posted.getNotification().extras
4910                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_ICON));
4911         assertFalse(posted.getNotification().extras
4912                 .containsKey(Notification.EXTRA_MEDIA_REMOTE_INTENT));
4913     }
4914 
4915     @Test
testSubstituteAppName_hasPermission()4916     public void testSubstituteAppName_hasPermission() throws RemoteException {
4917         String subName = "Substitute Name";
4918         mContext.getTestablePermissions().setPermission(
4919                 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_GRANTED);
4920         Bundle extras = new Bundle();
4921         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, subName);
4922         Notification.Builder nb = new Notification.Builder(mContext,
4923                 mTestNotificationChannel.getId())
4924                 .addExtras(extras);
4925         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4926                 "testSubstituteAppNamePermission", mUid, 0,
4927                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4928         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4929 
4930         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4931                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4932         waitForIdle();
4933         NotificationRecord posted = mService.findNotificationLocked(
4934                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4935 
4936         assertTrue(posted.getNotification().extras
4937                 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
4938         assertEquals(posted.getNotification().extras
4939                 .getString(Notification.EXTRA_SUBSTITUTE_APP_NAME), subName);
4940     }
4941 
4942     @Test
testSubstituteAppName_noPermission()4943     public void testSubstituteAppName_noPermission() throws RemoteException {
4944         mContext.getTestablePermissions().setPermission(
4945                 android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, PERMISSION_DENIED);
4946         Bundle extras = new Bundle();
4947         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Substitute Name");
4948         Notification.Builder nb = new Notification.Builder(mContext,
4949                 mTestNotificationChannel.getId())
4950                 .addExtras(extras);
4951         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4952                 "testSubstituteAppNamePermission", mUid, 0,
4953                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
4954         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4955 
4956         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
4957                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
4958         waitForIdle();
4959         NotificationRecord posted = mService.findNotificationLocked(
4960                 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
4961 
4962         assertFalse(posted.getNotification().extras
4963                 .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
4964     }
4965 
4966     @Test
testGetNotificationCountLocked()4967     public void testGetNotificationCountLocked() {
4968         String sampleTagToExclude = null;
4969         int sampleIdToExclude = 0;
4970         for (int i = 0; i < 20; i++) {
4971             NotificationRecord r =
4972                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
4973             mService.addEnqueuedNotification(r);
4974 
4975         }
4976         for (int i = 0; i < 20; i++) {
4977             NotificationRecord r =
4978                     generateNotificationRecord(mTestNotificationChannel, i, null, false);
4979             mService.addNotification(r);
4980             sampleTagToExclude = r.getSbn().getTag();
4981             sampleIdToExclude = i;
4982         }
4983 
4984         // another package
4985         Notification n =
4986                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4987                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4988                 .build();
4989 
4990         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
4991                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
4992         NotificationRecord otherPackage =
4993                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4994         mService.addEnqueuedNotification(otherPackage);
4995         mService.addNotification(otherPackage);
4996 
4997         // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
4998         // anything that's currently enqueued or posted
4999         int userId = mUserId;
5000         assertEquals(40,
5001                 mService.getNotificationCount(PKG, userId, 0, null));
5002         assertEquals(40,
5003                 mService.getNotificationCount(PKG, userId, 0, "tag2"));
5004 
5005         // return all for package "a" - "banana" tag isn't used
5006         assertEquals(2,
5007                 mService.getNotificationCount("a", userId, 0, "banana"));
5008 
5009         // exclude a known notification - it's excluded from only the posted list, not enqueued
5010         assertEquals(39, mService.getNotificationCount(
5011                 PKG, userId, sampleIdToExclude, sampleTagToExclude));
5012     }
5013 
5014     @Test
testAddAutogroup_requestsSort()5015     public void testAddAutogroup_requestsSort() throws Exception {
5016         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5017         mService.addNotification(r);
5018         mService.addAutogroupKeyLocked(r.getKey());
5019 
5020         verify(mRankingHandler, times(1)).requestSort();
5021     }
5022 
5023     @Test
testRemoveAutogroup_requestsSort()5024     public void testRemoveAutogroup_requestsSort() throws Exception {
5025         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5026         r.setOverrideGroupKey("TEST");
5027         mService.addNotification(r);
5028         mService.removeAutogroupKeyLocked(r.getKey());
5029 
5030         verify(mRankingHandler, times(1)).requestSort();
5031     }
5032 
5033     @Test
testReaddAutogroup_noSort()5034     public void testReaddAutogroup_noSort() throws Exception {
5035         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5036         r.setOverrideGroupKey("TEST");
5037         mService.addNotification(r);
5038         mService.addAutogroupKeyLocked(r.getKey());
5039 
5040         verify(mRankingHandler, never()).requestSort();
5041     }
5042 
5043     @Test
testHandleRankingSort_sendsUpdateOnSignalExtractorChange()5044     public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
5045         mService.setPreferencesHelper(mPreferencesHelper);
5046         NotificationManagerService.WorkerHandler handler = mock(
5047                 NotificationManagerService.WorkerHandler.class);
5048         mService.setHandler(handler);
5049 
5050         Map<String, Answer> answers = getSignalExtractorSideEffects();
5051         for (String message : answers.keySet()) {
5052             mService.clearNotifications();
5053             final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5054             mService.addNotification(r);
5055 
5056             doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
5057 
5058             mService.handleRankingSort();
5059         }
5060         verify(handler, times(answers.size())).scheduleSendRankingUpdate();
5061     }
5062 
5063     @Test
testHandleRankingSort_noUpdateWhenNoSignalChange()5064     public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
5065         mService.setRankingHelper(mRankingHelper);
5066         NotificationManagerService.WorkerHandler handler = mock(
5067                 NotificationManagerService.WorkerHandler.class);
5068         mService.setHandler(handler);
5069 
5070         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5071         mService.addNotification(r);
5072 
5073         mService.handleRankingSort();
5074         verify(handler, never()).scheduleSendRankingUpdate();
5075     }
5076 
5077     @Test
testReadPolicyXml_readApprovedServicesFromXml()5078     public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
5079         final String upgradeXml = "<notification-policy version=\"1\">"
5080                 + "<ranking></ranking>"
5081                 + "<enabled_listeners>"
5082                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
5083                 + "</enabled_listeners>"
5084                 + "<enabled_assistants>"
5085                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
5086                 + "</enabled_assistants>"
5087                 + "<dnd_apps>"
5088                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
5089                 + "</dnd_apps>"
5090                 + "</notification-policy>";
5091         mService.readPolicyXml(
5092                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
5093                 false,
5094                 UserHandle.USER_ALL);
5095         verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
5096         verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
5097         verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
5098 
5099         // numbers are inflated for setup
5100         verify(mListeners, times(1)).migrateToXml();
5101         verify(mConditionProviders, times(1)).migrateToXml();
5102         verify(mAssistants, times(1)).migrateToXml();
5103         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
5104     }
5105 
5106     @Test
testReadPolicyXml_readSnoozedNotificationsFromXml()5107     public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
5108         final String upgradeXml = "<notification-policy version=\"1\">"
5109                 + "<snoozed-notifications>></snoozed-notifications>"
5110                 + "</notification-policy>";
5111         mService.readPolicyXml(
5112                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
5113                 false,
5114                 UserHandle.USER_ALL);
5115         verify(mSnoozeHelper, times(1)).readXml(any(TypedXmlPullParser.class), anyLong());
5116     }
5117 
5118     @Test
testReadPolicyXml_readApprovedServicesFromSettings()5119     public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
5120         final String preupgradeXml = "<notification-policy version=\"1\">"
5121                 + "<ranking></ranking>"
5122                 + "</notification-policy>";
5123         mService.readPolicyXml(
5124                 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
5125                 false,
5126                 UserHandle.USER_ALL);
5127         verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
5128         verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
5129         verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
5130 
5131         // numbers are inflated for setup
5132         verify(mListeners, times(2)).migrateToXml();
5133         verify(mConditionProviders, times(2)).migrateToXml();
5134         verify(mAssistants, times(2)).migrateToXml();
5135         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
5136     }
5137 
5138     @Test
testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser()5139     public void testReadPolicyXml_doesNotRestoreManagedServicesForCloneUser() throws Exception {
5140         final String policyXml = "<notification-policy version=\"1\">"
5141                 + "<ranking></ranking>"
5142                 + "<enabled_listeners>"
5143                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5144                 + "</enabled_listeners>"
5145                 + "<enabled_assistants>"
5146                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5147                 + "</enabled_assistants>"
5148                 + "<dnd_apps>"
5149                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5150                 + "</dnd_apps>"
5151                 + "</notification-policy>";
5152         UserInfo ui = new UserInfo();
5153         ui.id = 10;
5154         ui.userType = USER_TYPE_PROFILE_CLONE;
5155         when(mUmInternal.getUserInfo(10)).thenReturn(ui);
5156         mService.readPolicyXml(
5157                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
5158                 true,
5159                 10);
5160         verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
5161         verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
5162         verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
5163     }
5164 
5165     @Test
testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser()5166     public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
5167         final String policyXml = "<notification-policy version=\"1\">"
5168                 + "<ranking></ranking>"
5169                 + "<enabled_listeners>"
5170                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5171                 + "</enabled_listeners>"
5172                 + "<enabled_assistants>"
5173                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5174                 + "</enabled_assistants>"
5175                 + "<dnd_apps>"
5176                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5177                 + "</dnd_apps>"
5178                 + "</notification-policy>";
5179         UserInfo ui = new UserInfo();
5180         ui.id = 10;
5181         ui.userType = USER_TYPE_PROFILE_MANAGED;
5182         when(mUmInternal.getUserInfo(10)).thenReturn(ui);
5183         mService.readPolicyXml(
5184                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
5185                 true,
5186                 10);
5187         verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
5188         verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
5189         verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
5190     }
5191 
5192     @Test
testReadPolicyXml_restoresManagedServicesForNonManagedUser()5193     public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
5194         final String policyXml = "<notification-policy version=\"1\">"
5195                 + "<ranking></ranking>"
5196                 + "<enabled_listeners>"
5197                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5198                 + "</enabled_listeners>"
5199                 + "<enabled_assistants>"
5200                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5201                 + "</enabled_assistants>"
5202                 + "<dnd_apps>"
5203                 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
5204                 + "</dnd_apps>"
5205                 + "</notification-policy>";
5206         UserInfo ui = new UserInfo();
5207         ui.id = 10;
5208         ui.userType = USER_TYPE_FULL_SECONDARY;
5209         when(mUmInternal.getUserInfo(10)).thenReturn(ui);
5210         mService.readPolicyXml(
5211                 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
5212                 true,
5213                 10);
5214         verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
5215         verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
5216         verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
5217     }
5218 
5219     @Test
testLocaleChangedCallsUpdateDefaultZenModeRules()5220     public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
5221         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
5222         mService.mZenModeHelper = mZenModeHelper;
5223         mService.mLocaleChangeReceiver.onReceive(mContext,
5224                 new Intent(Intent.ACTION_LOCALE_CHANGED));
5225 
5226         verify(mZenModeHelper, times(1)).updateDefaultZenRules(
5227                 anyInt(), anyBoolean());
5228     }
5229 
5230     @Test
testBumpFGImportance_channelChangePreOApp()5231     public void testBumpFGImportance_channelChangePreOApp() throws Exception {
5232         String preOPkg = PKG_N_MR1;
5233         final ApplicationInfo legacy = new ApplicationInfo();
5234         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
5235         when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
5236                 .thenReturn(legacy);
5237         when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
5238                 .thenReturn(Binder.getCallingUid());
5239         getContext().setMockPackageManager(mPackageManagerClient);
5240 
5241         Notification.Builder nb = new Notification.Builder(mContext,
5242                 NotificationChannel.DEFAULT_CHANNEL_ID)
5243                 .setContentTitle("foo")
5244                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5245                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
5246                 .setPriority(Notification.PRIORITY_MIN);
5247 
5248         StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
5249                 "testBumpFGImportance_channelChangePreOApp",
5250                 Binder.getCallingUid(), 0, nb.build(),
5251                 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
5252 
5253         mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
5254                 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
5255         waitForIdle();
5256 
5257         assertEquals(IMPORTANCE_LOW,
5258                 mService.getNotificationRecord(sbn.getKey()).getImportance());
5259         assertEquals(IMPORTANCE_DEFAULT, mBinderService.getPackageImportance(
5260                 sbn.getPackageName()));
5261 
5262         nb = new Notification.Builder(mContext)
5263                 .setContentTitle("foo")
5264                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5265                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
5266                 .setPriority(Notification.PRIORITY_MIN);
5267 
5268         sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
5269                 "testBumpFGImportance_channelChangePreOApp", Binder.getCallingUid(),
5270                 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
5271 
5272         mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
5273                 "testBumpFGImportance_channelChangePreOApp",
5274                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
5275         waitForIdle();
5276         assertEquals(IMPORTANCE_LOW,
5277                 mService.getNotificationRecord(sbn.getKey()).getImportance());
5278 
5279         NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
5280                 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
5281         assertEquals(IMPORTANCE_LOW, defaultChannel.getImportance());
5282     }
5283 
5284     @Test
testStats_updatedOnDirectReply()5285     public void testStats_updatedOnDirectReply() throws Exception {
5286         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5287         mService.addNotification(r);
5288 
5289         mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
5290         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
5291         verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r));
5292 
5293         assertEquals(1, mNotificationRecordLogger.numCalls());
5294         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
5295                 mNotificationRecordLogger.event(0));
5296     }
5297 
5298     @Test
testStats_updatedOnUserExpansion()5299     public void testStats_updatedOnUserExpansion() throws Exception {
5300         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5301         mService.addNotification(r);
5302 
5303         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
5304                 NOTIFICATION_LOCATION_UNKNOWN);
5305         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()),
5306                 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((true)));
5307         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5308 
5309         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
5310                 NOTIFICATION_LOCATION_UNKNOWN);
5311         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()),
5312                 eq(FLAG_FILTER_TYPE_ALERTING), eq(true), eq((false)));
5313         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5314 
5315         assertEquals(2, mNotificationRecordLogger.numCalls());
5316         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
5317                 mNotificationRecordLogger.event(0));
5318         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
5319                 mNotificationRecordLogger.event(1));
5320     }
5321 
5322     @Test
testStats_notUpdatedOnAutoExpansion()5323     public void testStats_notUpdatedOnAutoExpansion() throws Exception {
5324         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5325         mService.addNotification(r);
5326 
5327         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5328                 NOTIFICATION_LOCATION_UNKNOWN);
5329         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5330         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()),
5331                 eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((true)));
5332 
5333         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
5334                 NOTIFICATION_LOCATION_UNKNOWN);
5335         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
5336         verify(mAssistants).notifyAssistantExpansionChangedLocked(
5337                 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(false), eq((false)));
5338     }
5339 
5340     @Test
testStats_updatedOnViewSettings()5341     public void testStats_updatedOnViewSettings() throws Exception {
5342         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5343         mService.addNotification(r);
5344 
5345         mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
5346         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
5347     }
5348 
5349     @Test
testStats_updatedOnVisibilityChanged()5350     public void testStats_updatedOnVisibilityChanged() throws Exception {
5351         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5352         mService.addNotification(r);
5353 
5354         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
5355         mService.mNotificationDelegate.onNotificationVisibilityChanged(
5356                 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
5357         verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(true));
5358         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
5359         mService.mNotificationDelegate.onNotificationVisibilityChanged(
5360                 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
5361         verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r), eq(false));
5362         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
5363     }
5364 
5365     @Test
testStats_dismissalSurface()5366     public void testStats_dismissalSurface() throws Exception {
5367         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5368         r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5369         mService.addNotification(r);
5370 
5371         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
5372         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
5373                 r.getKey(), NotificationStats.DISMISSAL_AOD,
5374                 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
5375         waitForIdle();
5376 
5377         assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
5378 
5379         // Using mService.addNotification() does not generate a NotificationRecordLogger log,
5380         // so we only get the cancel notification.
5381         assertEquals(1, mNotificationRecordLogger.numCalls());
5382 
5383         assertEquals(
5384                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
5385                 mNotificationRecordLogger.event(0));
5386         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
5387     }
5388 
5389     @Test
testStats_dismissalSentiment()5390     public void testStats_dismissalSentiment() throws Exception {
5391         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5392         mService.addNotification(r);
5393 
5394         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
5395         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
5396                 r.getKey(), NotificationStats.DISMISSAL_AOD,
5397                 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
5398         waitForIdle();
5399 
5400         assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
5401                 r.getStats().getDismissalSentiment());
5402     }
5403 
5404     @Test
testTextChangedSet_forNewNotifs()5405     public void testTextChangedSet_forNewNotifs() throws Exception {
5406         NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
5407         mService.addEnqueuedNotification(original);
5408 
5409         NotificationManagerService.PostNotificationRunnable runnable =
5410                 mService.new PostNotificationRunnable(original.getKey(),
5411                         original.getSbn().getPackageName(),
5412                         original.getUid(),
5413                         mPostNotificationTrackerFactory.newTracker(null));
5414         runnable.run();
5415         waitForIdle();
5416 
5417         assertTrue(original.isTextChanged());
5418     }
5419 
5420     @Test
testVisuallyInterruptive_notSeen()5421     public void testVisuallyInterruptive_notSeen() throws Exception {
5422         NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
5423         mService.addNotification(original);
5424 
5425         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, original.getSbn().getId(),
5426                 original.getSbn().getTag(), mUid, 0,
5427                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
5428                         .setContentTitle("new title").build(),
5429                 UserHandle.getUserHandleForUid(mUid), null, 0);
5430         NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5431         mService.addEnqueuedNotification(update);
5432 
5433         NotificationManagerService.PostNotificationRunnable runnable =
5434                 mService.new PostNotificationRunnable(update.getKey(),
5435                         update.getSbn().getPackageName(),
5436                         update.getUid(),
5437                         mPostNotificationTrackerFactory.newTracker(null));
5438         runnable.run();
5439         waitForIdle();
5440 
5441         assertFalse(update.isInterruptive());
5442     }
5443 
5444     @Test
testApplyAdjustmentMultiUser()5445     public void testApplyAdjustmentMultiUser() throws Exception {
5446         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5447         mService.addNotification(r);
5448         NotificationManagerService.WorkerHandler handler = mock(
5449                 NotificationManagerService.WorkerHandler.class);
5450         mService.setHandler(handler);
5451 
5452         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
5453 
5454         Bundle signals = new Bundle();
5455         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5456                 USER_SENTIMENT_NEGATIVE);
5457         Adjustment adjustment = new Adjustment(
5458                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5459         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5460 
5461         waitForIdle();
5462 
5463         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
5464     }
5465 
5466     @Test
testAssistantBlockingTriggersCancel()5467     public void testAssistantBlockingTriggersCancel() throws Exception {
5468         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5469         mService.addNotification(r);
5470         NotificationManagerService.WorkerHandler handler = mock(
5471                 NotificationManagerService.WorkerHandler.class);
5472         mService.setHandler(handler);
5473 
5474         Bundle signals = new Bundle();
5475         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
5476         Adjustment adjustment = new Adjustment(
5477                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5478         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
5479         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5480 
5481         waitForIdle();
5482 
5483         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
5484         verify(handler, times(1)).scheduleCancelNotification(any());
5485     }
5486 
5487     @Test
testApplyEnqueuedAdjustmentFromAssistant_singleUser()5488     public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
5489         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5490         mService.addEnqueuedNotification(r);
5491         NotificationManagerService.WorkerHandler handler = mock(
5492                 NotificationManagerService.WorkerHandler.class);
5493         mService.setHandler(handler);
5494         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5495 
5496         Bundle signals = new Bundle();
5497         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5498                 USER_SENTIMENT_NEGATIVE);
5499         Adjustment adjustment = new Adjustment(
5500                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5501         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5502 
5503         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
5504     }
5505 
5506     @Test
testApplyEnqueuedAdjustmentFromAssistant_importance()5507     public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
5508         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5509         mService.addEnqueuedNotification(r);
5510         NotificationManagerService.WorkerHandler handler = mock(
5511                 NotificationManagerService.WorkerHandler.class);
5512         mService.setHandler(handler);
5513         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5514 
5515         Bundle signals = new Bundle();
5516         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5517         Adjustment adjustment = new Adjustment(
5518                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5519         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5520 
5521         assertEquals(IMPORTANCE_LOW, r.getImportance());
5522     }
5523 
5524     @Test
testApplyEnqueuedAdjustmentFromAssistant_crossUser()5525     public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
5526         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5527         mService.addEnqueuedNotification(r);
5528         NotificationManagerService.WorkerHandler handler = mock(
5529                 NotificationManagerService.WorkerHandler.class);
5530         mService.setHandler(handler);
5531         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
5532 
5533         Bundle signals = new Bundle();
5534         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5535                 USER_SENTIMENT_NEGATIVE);
5536         Adjustment adjustment = new Adjustment(
5537                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5538         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5539 
5540         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5541 
5542         waitForIdle();
5543 
5544         verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
5545     }
5546 
5547     @Test
testUserSentimentChangeTriggersUpdate()5548     public void testUserSentimentChangeTriggersUpdate() throws Exception {
5549         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5550         mService.addNotification(r);
5551         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5552 
5553         Bundle signals = new Bundle();
5554         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5555                 USER_SENTIMENT_NEGATIVE);
5556         Adjustment adjustment = new Adjustment(
5557                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5558         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5559 
5560         waitForIdle();
5561 
5562         verify(mRankingHandler, timeout(300).times(1)).requestSort();
5563     }
5564 
5565     @Test
testTooLateAdjustmentTriggersUpdate()5566     public void testTooLateAdjustmentTriggersUpdate() throws Exception {
5567         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5568         mService.addNotification(r);
5569         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5570 
5571         Bundle signals = new Bundle();
5572         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5573                 USER_SENTIMENT_NEGATIVE);
5574         Adjustment adjustment = new Adjustment(
5575                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5576         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5577 
5578         waitForIdle();
5579 
5580         verify(mRankingHandler, times(1)).requestSort();
5581     }
5582 
5583     @Test
testApplyAdjustmentsLogged()5584     public void testApplyAdjustmentsLogged() throws Exception {
5585         NotificationManagerService.WorkerHandler handler = mock(
5586                 NotificationManagerService.WorkerHandler.class);
5587         mService.setHandler(handler);
5588         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5589 
5590         // Set up notifications that will be adjusted
5591         final NotificationRecord r1 = generateNotificationRecord(
5592                 mTestNotificationChannel, 1, null, true);
5593         r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5594         mService.addNotification(r1);
5595         final NotificationRecord r2 = generateNotificationRecord(
5596                 mTestNotificationChannel, 2, null, true);
5597         r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5598         mService.addNotification(r2);
5599 
5600         // Third notification that's NOT adjusted, just to make sure that doesn't get spuriously
5601         // logged.
5602         final NotificationRecord r3 = generateNotificationRecord(
5603                 mTestNotificationChannel, 3, null, true);
5604         r3.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5605         mService.addNotification(r3);
5606 
5607         List<Adjustment> adjustments = new ArrayList<>();
5608 
5609         // Test an adjustment that's associated with a ranking change and one that's not
5610         Bundle signals1 = new Bundle();
5611         signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_HIGH);
5612         Adjustment adjustment1 = new Adjustment(
5613                 r1.getSbn().getPackageName(), r1.getKey(), signals1, "",
5614                 r1.getUser().getIdentifier());
5615         adjustments.add(adjustment1);
5616 
5617         // This one wouldn't trigger a ranking change, but should still trigger a log.
5618         Bundle signals2 = new Bundle();
5619         signals2.putFloat(Adjustment.KEY_RANKING_SCORE, -0.5f);
5620         Adjustment adjustment2 = new Adjustment(
5621                 r2.getSbn().getPackageName(), r2.getKey(), signals2, "",
5622                 r2.getUser().getIdentifier());
5623         adjustments.add(adjustment2);
5624 
5625         mBinderService.applyAdjustmentsFromAssistant(null, adjustments);
5626         verify(mRankingHandler, times(1)).requestSort();
5627 
5628         // Actually apply the adjustments & recalculate importance when run
5629         doAnswer(invocationOnMock -> {
5630             ((NotificationRecord) invocationOnMock.getArguments()[0])
5631                     .applyAdjustments();
5632             ((NotificationRecord) invocationOnMock.getArguments()[0])
5633                     .calculateImportance();
5634             return null;
5635         }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
5636 
5637         // Now make sure that when the sort happens, we actually log the changes.
5638         mService.handleRankingSort();
5639 
5640         // Even though the ranking score change is not meant to trigger a ranking update,
5641         // during this process the package visibility & canShowBadge values are changing
5642         // in all notifications, so all 3 seem to trigger a ranking change. Here we check instead
5643         // that scheduleSendRankingUpdate is sent and that the relevant fields have been changed
5644         // accordingly to confirm the adjustments happened to the 2 relevant notifications.
5645         verify(handler, times(3)).scheduleSendRankingUpdate();
5646         assertEquals(IMPORTANCE_HIGH, r1.getImportance());
5647         assertTrue(r2.rankingScoreMatches(-0.5f));
5648         assertEquals(2, mNotificationRecordLogger.numCalls());
5649         assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(0));
5650         assertEquals(NOTIFICATION_ADJUSTED, mNotificationRecordLogger.event(1));
5651         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
5652         assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId());
5653     }
5654 
5655     @Test
testAdjustmentToImportanceNone_cancelsNotification()5656     public void testAdjustmentToImportanceNone_cancelsNotification() throws Exception {
5657         NotificationManagerService.WorkerHandler handler = mock(
5658                 NotificationManagerService.WorkerHandler.class);
5659         mService.setHandler(handler);
5660         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5661         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
5662 
5663         // Set up notifications: r1 is adjusted, r2 is not
5664         final NotificationRecord r1 = generateNotificationRecord(
5665                 mTestNotificationChannel, 1, null, true);
5666         r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5667         mService.addNotification(r1);
5668         final NotificationRecord r2 = generateNotificationRecord(
5669                 mTestNotificationChannel, 2, null, true);
5670         r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
5671         mService.addNotification(r2);
5672 
5673         // Test an adjustment that sets importance to none (meaning it's cancelling)
5674         Bundle signals1 = new Bundle();
5675         signals1.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE);
5676         Adjustment adjustment1 = new Adjustment(
5677                 r1.getSbn().getPackageName(), r1.getKey(), signals1, "",
5678                 r1.getUser().getIdentifier());
5679 
5680         mBinderService.applyAdjustmentFromAssistant(null, adjustment1);
5681 
5682         // Actually apply the adjustments & recalculate importance when run
5683         doAnswer(invocationOnMock -> {
5684             ((NotificationRecord) invocationOnMock.getArguments()[0])
5685                     .applyAdjustments();
5686             ((NotificationRecord) invocationOnMock.getArguments()[0])
5687                     .calculateImportance();
5688             return null;
5689         }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
5690 
5691         // run the CancelNotificationRunnable when it happens
5692         ArgumentCaptor<NotificationManagerService.CancelNotificationRunnable> captor =
5693                 ArgumentCaptor.forClass(
5694                         NotificationManagerService.CancelNotificationRunnable.class);
5695 
5696         verify(handler, times(1)).scheduleCancelNotification(
5697                 captor.capture());
5698 
5699         // Run the runnable given to the cancel notification, and see if it logs properly
5700         NotificationManagerService.CancelNotificationRunnable runnable = captor.getValue();
5701         runnable.run();
5702         assertEquals(1, mNotificationRecordLogger.numCalls());
5703         assertEquals(
5704                 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_ASSISTANT,
5705                 mNotificationRecordLogger.event(0));
5706     }
5707 
5708     @Test
testEnqueuedAdjustmentAppliesAdjustments()5709     public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
5710         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5711         mService.addEnqueuedNotification(r);
5712         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5713 
5714         Bundle signals = new Bundle();
5715         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
5716                 USER_SENTIMENT_NEGATIVE);
5717         Adjustment adjustment = new Adjustment(
5718                 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
5719         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5720 
5721         assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
5722     }
5723 
5724     @Test
testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications()5725     public void testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications() throws Exception {
5726         final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel);
5727         final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel);
5728         mService.addEnqueuedNotification(r1);
5729         mService.addEnqueuedNotification(r2);
5730         when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
5731 
5732         Bundle signals = new Bundle();
5733         signals.putInt(Adjustment.KEY_IMPORTANCE,
5734                 IMPORTANCE_HIGH);
5735         Adjustment adjustment = new Adjustment(
5736                 r1.getSbn().getPackageName(), r1.getKey(), signals,
5737                 "", r1.getUser().getIdentifier());
5738 
5739         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
5740 
5741         assertEquals(IMPORTANCE_HIGH, r1.getImportance());
5742         assertEquals(IMPORTANCE_HIGH, r2.getImportance());
5743     }
5744 
5745     @Test
testRestore()5746     public void testRestore() throws Exception {
5747         int systemChecks = mService.countSystemChecks;
5748         mBinderService.applyRestore(null, USER_SYSTEM);
5749         assertEquals(1, mService.countSystemChecks - systemChecks);
5750     }
5751 
5752     @Test
testBackupEmptySound()5753     public void testBackupEmptySound() throws Exception {
5754         NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
5755         channel.setSound(Uri.EMPTY, null);
5756 
5757         TypedXmlSerializer serializer = Xml.newFastSerializer();
5758         ByteArrayOutputStream baos = new ByteArrayOutputStream();
5759         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
5760         channel.writeXmlForBackup(serializer, getContext());
5761 
5762         TypedXmlPullParser parser = Xml.newFastPullParser();
5763         parser.setInput(new BufferedInputStream(
5764                 new ByteArrayInputStream(baos.toByteArray())), null);
5765         NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
5766         restored.populateFromXmlForRestore(parser, true, getContext());
5767 
5768         assertNull(restored.getSound());
5769     }
5770 
5771     @Test
testBackup()5772     public void testBackup() throws Exception {
5773         mService.setPreferencesHelper(mPreferencesHelper);
5774         int systemChecks = mService.countSystemChecks;
5775         when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
5776                 .thenReturn(new ArraySet<>());
5777         mBinderService.getBackupPayload(1);
5778         assertEquals(1, mService.countSystemChecks - systemChecks);
5779     }
5780 
5781     @Test
testEmptyVibration_noException()5782     public void testEmptyVibration_noException() throws Exception {
5783         NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
5784         channel.setVibrationPattern(new long[0]);
5785 
5786         TypedXmlSerializer serializer = Xml.newFastSerializer();
5787         ByteArrayOutputStream baos = new ByteArrayOutputStream();
5788         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
5789         channel.writeXml(serializer);
5790     }
5791 
5792     @Test
updateUriPermissions_update()5793     public void updateUriPermissions_update() throws Exception {
5794         NotificationChannel c = new NotificationChannel(
5795                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
5796         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
5797         Message message1 = new Message("", 0, "");
5798         message1.setData("",
5799                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
5800         Message message2 = new Message("", 1, "");
5801         message2.setData("",
5802                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
5803 
5804         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
5805                 .setContentTitle("foo")
5806                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5807                 .setStyle(new Notification.MessagingStyle("")
5808                         .addMessage(message1)
5809                         .addMessage(message2));
5810         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
5811                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
5812                 null, 0), c);
5813 
5814         // First post means we grant access to both
5815         reset(mUgm);
5816         reset(mUgmInternal);
5817         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
5818         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
5819                 USER_SYSTEM);
5820         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
5821                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
5822         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
5823                 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
5824 
5825         Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
5826                 .setContentTitle("foo")
5827                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5828                 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
5829         NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
5830                 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
5831                 c);
5832 
5833         // Update means we drop access to first
5834         reset(mUgmInternal);
5835         mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
5836                 USER_SYSTEM);
5837         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
5838                 eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1));
5839 
5840         // Update back means we grant access to first again
5841         reset(mUgm);
5842         mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
5843                 USER_SYSTEM);
5844         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
5845                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
5846 
5847         // And update to empty means we drop everything
5848         reset(mUgmInternal);
5849         mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
5850                 USER_SYSTEM);
5851         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
5852                 anyInt(), anyInt());
5853     }
5854 
5855     @Test
updateUriPermissions_posterDoesNotOwnUri()5856     public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
5857         NotificationChannel c = new NotificationChannel(
5858                 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
5859         c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
5860         Message message1 = new Message("", 0, "");
5861         message1.setData("",
5862                 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
5863 
5864         Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
5865                 .setContentTitle("foo")
5866                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5867                 .setStyle(new Notification.MessagingStyle("")
5868                         .addMessage(message1));
5869         NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
5870                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
5871                 null, 0), c);
5872 
5873         doThrow(new SecurityException("no access")).when(mUgm)
5874                 .grantUriPermissionFromOwner(
5875                         any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
5876 
5877         when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
5878         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),  USER_SYSTEM);
5879 
5880         // yay, no crash
5881     }
5882 
5883     @Test
testVisitUris()5884     public void testVisitUris() throws Exception {
5885         final Uri audioContents = Uri.parse("content://com.example/audio");
5886         final Uri backgroundImage = Uri.parse("content://com.example/background");
5887         final Icon smallIcon = Icon.createWithContentUri("content://media/small/icon");
5888         final Icon largeIcon = Icon.createWithContentUri("content://media/large/icon");
5889         final Icon personIcon1 = Icon.createWithContentUri("content://media/person1");
5890         final Icon personIcon2 = Icon.createWithContentUri("content://media/person2");
5891         final Icon personIcon3 = Icon.createWithContentUri("content://media/person3");
5892         final Person person1 = new Person.Builder()
5893                 .setName("Messaging Person")
5894                 .setIcon(personIcon1)
5895                 .build();
5896         final Person person2 = new Person.Builder()
5897                 .setName("People List Person 1")
5898                 .setIcon(personIcon2)
5899                 .build();
5900         final Person person3 = new Person.Builder()
5901                 .setName("People List Person 2")
5902                 .setIcon(personIcon3)
5903                 .build();
5904         final Uri historyUri1 = Uri.parse("content://com.example/history1");
5905         final Uri historyUri2 = Uri.parse("content://com.example/history2");
5906         final RemoteInputHistoryItem historyItem1 = new RemoteInputHistoryItem(null, historyUri1,
5907                 "a");
5908         final RemoteInputHistoryItem historyItem2 = new RemoteInputHistoryItem(null, historyUri2,
5909                 "b");
5910 
5911         Bundle extras = new Bundle();
5912         extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
5913         extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
5914         extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1);
5915         extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST,
5916                 new ArrayList<>(Arrays.asList(person2, person3)));
5917         extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
5918                 new RemoteInputHistoryItem[]{historyItem1, historyItem2});
5919 
5920         Notification n = new Notification.Builder(mContext, "a")
5921                 .setContentTitle("notification with uris")
5922                 .setSmallIcon(smallIcon)
5923                 .setLargeIcon(largeIcon)
5924                 .addExtras(extras)
5925                 .build();
5926 
5927         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
5928         n.visitUris(visitor);
5929         verify(visitor, times(1)).accept(eq(audioContents));
5930         verify(visitor, times(1)).accept(eq(backgroundImage));
5931         verify(visitor, times(1)).accept(eq(smallIcon.getUri()));
5932         verify(visitor, times(1)).accept(eq(largeIcon.getUri()));
5933         verify(visitor, times(1)).accept(eq(personIcon1.getUri()));
5934         verify(visitor, times(1)).accept(eq(personIcon2.getUri()));
5935         verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
5936         verify(visitor, times(1)).accept(eq(historyUri1));
5937         verify(visitor, times(1)).accept(eq(historyUri2));
5938     }
5939 
5940     @Test
testVisitUris_publicVersion()5941     public void testVisitUris_publicVersion() throws Exception {
5942         final Icon smallIconPublic = Icon.createWithContentUri("content://media/small/icon");
5943         final Icon largeIconPrivate = Icon.createWithContentUri("content://media/large/icon");
5944 
5945         Notification publicVersion = new Notification.Builder(mContext, "a")
5946                 .setContentTitle("notification with uris")
5947                 .setSmallIcon(smallIconPublic)
5948                 .build();
5949         Notification n = new Notification.Builder(mContext, "a")
5950                 .setLargeIcon(largeIconPrivate)
5951                 .setPublicVersion(publicVersion)
5952                 .build();
5953 
5954         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
5955         n.visitUris(visitor);
5956         verify(visitor, times(1)).accept(eq(smallIconPublic.getUri()));
5957         verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri()));
5958     }
5959 
5960     @Test
testVisitUris_audioContentsString()5961     public void testVisitUris_audioContentsString() throws Exception {
5962         final Uri audioContents = Uri.parse("content://com.example/audio");
5963 
5964         Bundle extras = new Bundle();
5965         extras.putString(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents.toString());
5966 
5967         Notification n = new Notification.Builder(mContext, "a")
5968                 .setContentTitle("notification with uris")
5969                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5970                 .addExtras(extras)
5971                 .build();
5972 
5973         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
5974         n.visitUris(visitor);
5975         verify(visitor, times(1)).accept(eq(audioContents));
5976     }
5977 
5978     @Test
testVisitUris_messagingStyle()5979     public void testVisitUris_messagingStyle() {
5980         final Icon personIcon1 = Icon.createWithContentUri("content://media/person1");
5981         final Icon personIcon2 = Icon.createWithContentUri("content://media/person2");
5982         final Icon personIcon3 = Icon.createWithContentUri("content://media/person3");
5983         final Person person1 = new Person.Builder()
5984                 .setName("Messaging Person 1")
5985                 .setIcon(personIcon1)
5986                 .build();
5987         final Person person2 = new Person.Builder()
5988                 .setName("Messaging Person 2")
5989                 .setIcon(personIcon2)
5990                 .build();
5991         final Person person3 = new Person.Builder()
5992                 .setName("Messaging Person 3")
5993                 .setIcon(personIcon3)
5994                 .build();
5995         Icon shortcutIcon = Icon.createWithContentUri("content://media/shortcut");
5996 
5997         Notification.Builder builder = new Notification.Builder(mContext, "a")
5998                 .setCategory(Notification.CATEGORY_MESSAGE)
5999                 .setContentTitle("new message!")
6000                 .setContentText("Conversation Notification")
6001                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
6002         Notification.MessagingStyle.Message message1 = new Notification.MessagingStyle.Message(
6003                 "Marco?", System.currentTimeMillis(), person2);
6004         Notification.MessagingStyle.Message message2 = new Notification.MessagingStyle.Message(
6005                 "Polo!", System.currentTimeMillis(), person3);
6006         Notification.MessagingStyle style = new Notification.MessagingStyle(person1)
6007                 .addMessage(message1)
6008                 .addMessage(message2)
6009                 .setShortcutIcon(shortcutIcon);
6010         builder.setStyle(style);
6011         Notification n = builder.build();
6012 
6013         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6014         n.visitUris(visitor);
6015 
6016         verify(visitor, times(1)).accept(eq(shortcutIcon.getUri()));
6017         verify(visitor, times(1)).accept(eq(personIcon1.getUri()));
6018         verify(visitor, times(1)).accept(eq(personIcon2.getUri()));
6019         verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
6020     }
6021 
6022     @Test
testVisitUris_callStyle()6023     public void testVisitUris_callStyle() {
6024         Icon personIcon = Icon.createWithContentUri("content://media/person");
6025         Icon verificationIcon = Icon.createWithContentUri("content://media/verification");
6026         Person callingPerson = new Person.Builder().setName("Someone")
6027                 .setIcon(personIcon)
6028                 .build();
6029         PendingIntent hangUpIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
6030                 PendingIntent.FLAG_IMMUTABLE);
6031         Notification n = new Notification.Builder(mContext, "a")
6032                 .setStyle(Notification.CallStyle.forOngoingCall(callingPerson, hangUpIntent)
6033                         .setVerificationIcon(verificationIcon))
6034                 .setContentTitle("Calling...")
6035                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6036                 .build();
6037 
6038         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6039         n.visitUris(visitor);
6040 
6041         verify(visitor, times(1)).accept(eq(personIcon.getUri()));
6042         verify(visitor, times(1)).accept(eq(verificationIcon.getUri()));
6043     }
6044 
6045     @Test
testVisitUris_styleExtrasWithoutStyle()6046     public void testVisitUris_styleExtrasWithoutStyle() {
6047         Notification notification = new Notification.Builder(mContext, "a")
6048                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6049                 .build();
6050 
6051         Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(
6052                 personWithIcon("content://user"))
6053                 .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!",
6054                                 System.currentTimeMillis(),
6055                                 personWithIcon("content://historicalMessenger")))
6056                 .addMessage(new Notification.MessagingStyle.Message("Are you there",
6057                                 System.currentTimeMillis(),
6058                                 personWithIcon("content://messenger")))
6059                         .setShortcutIcon(
6060                                 Icon.createWithContentUri("content://conversationShortcut"));
6061         messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style).
6062 
6063         Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall(
6064                         personWithIcon("content://caller"),
6065                         PendingIntent.getActivity(mContext, 0, new Intent(),
6066                                 PendingIntent.FLAG_IMMUTABLE))
6067                 .setVerificationIcon(Icon.createWithContentUri("content://callVerification"));
6068         callStyle.addExtras(notification.extras); // Same.
6069 
6070         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6071         notification.visitUris(visitor);
6072 
6073         verify(visitor).accept(eq(Uri.parse("content://user")));
6074         verify(visitor).accept(eq(Uri.parse("content://historicalMessenger")));
6075         verify(visitor).accept(eq(Uri.parse("content://messenger")));
6076         verify(visitor).accept(eq(Uri.parse("content://conversationShortcut")));
6077         verify(visitor).accept(eq(Uri.parse("content://caller")));
6078         verify(visitor).accept(eq(Uri.parse("content://callVerification")));
6079     }
6080 
personWithIcon(String iconUri)6081     private static Person personWithIcon(String iconUri) {
6082         return new Person.Builder()
6083                 .setName("Mr " + iconUri)
6084                 .setIcon(Icon.createWithContentUri(iconUri))
6085                 .build();
6086     }
6087 
6088     @Test
testVisitUris_wearableExtender()6089     public void testVisitUris_wearableExtender() {
6090         Icon actionIcon = Icon.createWithContentUri("content://media/action");
6091         Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction");
6092         PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(),
6093                 PendingIntent.FLAG_IMMUTABLE);
6094         Notification n = new Notification.Builder(mContext, "a")
6095                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6096                 .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build())
6097                 .extend(new Notification.WearableExtender().addAction(
6098                         new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build()))
6099                 .build();
6100 
6101         Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
6102         n.visitUris(visitor);
6103 
6104         verify(visitor).accept(eq(actionIcon.getUri()));
6105         verify(visitor).accept(eq(wearActionIcon.getUri()));
6106     }
6107 
6108     @Test
testSetNotificationPolicy_preP_setOldFields()6109     public void testSetNotificationPolicy_preP_setOldFields() {
6110         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6111         mService.mZenModeHelper = mZenModeHelper;
6112         NotificationManager.Policy userPolicy =
6113                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6114         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6115 
6116         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6117                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
6118 
6119         int expected = SUPPRESSED_EFFECT_BADGE
6120                 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
6121                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
6122                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6123         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
6124 
6125         assertEquals(expected, actual);
6126     }
6127 
6128     @Test
testSetNotificationPolicy_preP_setNewFields()6129     public void testSetNotificationPolicy_preP_setNewFields() {
6130         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6131         mService.mZenModeHelper = mZenModeHelper;
6132         NotificationManager.Policy userPolicy =
6133                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6134         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6135 
6136         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6137                 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
6138 
6139         int expected = SUPPRESSED_EFFECT_BADGE;
6140         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
6141 
6142         assertEquals(expected, actual);
6143     }
6144 
6145     @Test
testSetNotificationPolicy_preP_setOldNewFields()6146     public void testSetNotificationPolicy_preP_setOldNewFields() {
6147         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6148         mService.mZenModeHelper = mZenModeHelper;
6149         NotificationManager.Policy userPolicy =
6150                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6151         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6152 
6153         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6154                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
6155 
6156         int expected =
6157                 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
6158         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
6159 
6160         assertEquals(expected, actual);
6161     }
6162 
6163     @Test
testSetNotificationPolicy_P_setOldFields()6164     public void testSetNotificationPolicy_P_setOldFields() {
6165         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6166         mService.mZenModeHelper = mZenModeHelper;
6167         NotificationManager.Policy userPolicy =
6168                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6169         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6170 
6171         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6172                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
6173 
6174         int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
6175                 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
6176                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6177         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6178 
6179         assertEquals(expected, actual);
6180     }
6181 
6182     @Test
testSetNotificationPolicy_P_setNewFields()6183     public void testSetNotificationPolicy_P_setNewFields() {
6184         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6185         mService.mZenModeHelper = mZenModeHelper;
6186         NotificationManager.Policy userPolicy =
6187                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6188         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6189 
6190         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6191                 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
6192                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
6193 
6194         int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
6195                 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
6196                 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6197         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6198 
6199         assertEquals(expected, actual);
6200     }
6201 
6202     @Test
testSetNotificationPolicy_P_setOldNewFields()6203     public void testSetNotificationPolicy_P_setOldNewFields() {
6204         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
6205         mService.mZenModeHelper = mZenModeHelper;
6206         NotificationManager.Policy userPolicy =
6207                 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
6208         when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
6209 
6210         NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
6211                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
6212 
6213         int expected =  SUPPRESSED_EFFECT_STATUS_BAR;
6214         int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6215 
6216         assertEquals(expected, actual);
6217 
6218         appPolicy = new NotificationManager.Policy(0, 0, 0,
6219                 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
6220                         | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
6221 
6222         expected =  SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
6223                 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
6224         actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
6225 
6226         assertEquals(expected, actual);
6227     }
6228 
6229     @Test
testVisualDifference_foreground()6230     public void testVisualDifference_foreground() {
6231         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6232                 .setContentTitle("foo");
6233         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6234                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6235         NotificationRecord r1 =
6236                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6237 
6238         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6239                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
6240                 .setContentTitle("bar");
6241         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6242                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6243         NotificationRecord r2 =
6244                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6245 
6246         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6247     }
6248 
6249     @Test
testVisualDifference_diffTitle()6250     public void testVisualDifference_diffTitle() {
6251         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6252                 .setContentTitle("foo");
6253         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6254                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6255         NotificationRecord r1 =
6256                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6257 
6258         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6259                 .setContentTitle("bar");
6260         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6261                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6262         NotificationRecord r2 =
6263                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6264 
6265         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6266     }
6267 
6268     @Test
testVisualDifference_inboxStyle()6269     public void testVisualDifference_inboxStyle() {
6270         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6271                 .setStyle(new Notification.InboxStyle()
6272                     .addLine("line1").addLine("line2"));
6273         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6274                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6275         NotificationRecord r1 =
6276                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6277 
6278         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6279                 .setStyle(new Notification.InboxStyle()
6280                         .addLine("line1").addLine("line2_changed"));
6281         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6282                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6283         NotificationRecord r2 =
6284                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6285 
6286         assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
6287 
6288         Notification.Builder nb3 = new Notification.Builder(mContext, "")
6289                 .setStyle(new Notification.InboxStyle()
6290                         .addLine("line1"));
6291         StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6292                 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6293         NotificationRecord r3 =
6294                 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
6295 
6296         assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
6297 
6298         Notification.Builder nb4 = new Notification.Builder(mContext, "")
6299                 .setStyle(new Notification.InboxStyle()
6300                         .addLine("line1").addLine("line2").addLine("line3"));
6301         StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6302                 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6303         NotificationRecord r4 =
6304                 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
6305 
6306         assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
6307 
6308         Notification.Builder nb5 = new Notification.Builder(mContext, "")
6309             .setContentText("not an inbox");
6310         StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6311                 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6312         NotificationRecord r5 =
6313                 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
6314 
6315         assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
6316     }
6317 
6318     @Test
testVisualDifference_diffText()6319     public void testVisualDifference_diffText() {
6320         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6321                 .setContentText("foo");
6322         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6323                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6324         NotificationRecord r1 =
6325                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6326 
6327         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6328                 .setContentText("bar");
6329         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6330                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6331         NotificationRecord r2 =
6332                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6333 
6334         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6335     }
6336 
6337     @Test
testVisualDifference_sameText()6338     public void testVisualDifference_sameText() {
6339         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6340                 .setContentText("foo");
6341         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6342                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6343         NotificationRecord r1 =
6344                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6345 
6346         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6347                 .setContentText("foo");
6348         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6349                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6350         NotificationRecord r2 =
6351                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6352 
6353         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6354     }
6355 
6356     @Test
testVisualDifference_sameTextButStyled()6357     public void testVisualDifference_sameTextButStyled() {
6358         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6359                 .setContentText(Html.fromHtml("<b>foo</b>"));
6360         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6361                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6362         NotificationRecord r1 =
6363                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6364 
6365         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6366                 .setContentText(Html.fromHtml("<b>foo</b>"));
6367         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6368                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6369         NotificationRecord r2 =
6370                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6371 
6372         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6373     }
6374 
6375     @Test
testVisualDifference_diffTextButStyled()6376     public void testVisualDifference_diffTextButStyled() {
6377         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6378                 .setContentText(Html.fromHtml("<b>foo</b>"));
6379         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6380                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6381         NotificationRecord r1 =
6382                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6383 
6384         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6385                 .setContentText(Html.fromHtml("<b>bar</b>"));
6386         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6387                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6388         NotificationRecord r2 =
6389                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6390 
6391         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6392     }
6393 
6394     @Test
testVisualDifference_diffProgress()6395     public void testVisualDifference_diffProgress() {
6396         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6397                 .setProgress(100, 90, false);
6398         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6399                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6400         NotificationRecord r1 =
6401                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6402 
6403         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6404                 .setProgress(100, 100, false);
6405         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6406                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6407         NotificationRecord r2 =
6408                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6409 
6410         assertTrue(mService.isVisuallyInterruptive(r1, r2));
6411     }
6412 
6413     @Test
testVisualDifference_diffProgressNotDone()6414     public void testVisualDifference_diffProgressNotDone() {
6415         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6416                 .setProgress(100, 90, false);
6417         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6418                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6419         NotificationRecord r1 =
6420                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6421 
6422         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6423                 .setProgress(100, 91, false);
6424         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6425                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6426         NotificationRecord r2 =
6427                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6428 
6429         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6430     }
6431 
6432     @Test
testVisualDifference_sameProgressStillDone()6433     public void testVisualDifference_sameProgressStillDone() {
6434         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6435                 .setProgress(100, 100, false);
6436         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6437                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6438         NotificationRecord r1 =
6439                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6440 
6441         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6442                 .setProgress(100, 100, false);
6443         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6444                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6445         NotificationRecord r2 =
6446                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6447 
6448         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6449     }
6450 
6451     @Test
testVisualDifference_summary()6452     public void testVisualDifference_summary() {
6453         Notification.Builder nb1 = new Notification.Builder(mContext, "")
6454                 .setGroup("bananas")
6455                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
6456                 .setContentText("foo");
6457         StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6458                 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6459         NotificationRecord r1 =
6460                 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
6461 
6462         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6463                 .setGroup("bananas")
6464                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
6465                 .setContentText("bar");
6466         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6467                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6468         NotificationRecord r2 =
6469                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6470 
6471         assertFalse(mService.isVisuallyInterruptive(r1, r2));
6472     }
6473 
6474     @Test
testVisualDifference_summaryNewNotification()6475     public void testVisualDifference_summaryNewNotification() {
6476         Notification.Builder nb2 = new Notification.Builder(mContext, "")
6477                 .setGroup("bananas")
6478                 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
6479                 .setContentText("bar");
6480         StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
6481                 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
6482         NotificationRecord r2 =
6483                 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
6484 
6485         assertFalse(mService.isVisuallyInterruptive(null, r2));
6486     }
6487 
6488     @Test
testVisualDifference_sameImages()6489     public void testVisualDifference_sameImages() {
6490         Icon large = Icon.createWithResource(mContext, 1);
6491         Notification n1 = new Notification.Builder(mContext, "channel")
6492                 .setSmallIcon(1).setLargeIcon(large).build();
6493         Notification n2 = new Notification.Builder(mContext, "channel")
6494                 .setSmallIcon(1).setLargeIcon(large).build();
6495 
6496         NotificationRecord r1 = notificationToRecord(n1);
6497         NotificationRecord r2 = notificationToRecord(n2);
6498 
6499         assertThat(mService.isVisuallyInterruptive(r1, r2)).isFalse();
6500     }
6501 
6502     @Test
testVisualDifference_differentSmallImage()6503     public void testVisualDifference_differentSmallImage() {
6504         Icon large = Icon.createWithResource(mContext, 1);
6505         Notification n1 = new Notification.Builder(mContext, "channel")
6506                 .setSmallIcon(1).setLargeIcon(large).build();
6507         Notification n2 = new Notification.Builder(mContext, "channel")
6508                 .setSmallIcon(2).setLargeIcon(large).build();
6509 
6510         NotificationRecord r1 = notificationToRecord(n1);
6511         NotificationRecord r2 = notificationToRecord(n2);
6512 
6513         assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue();
6514     }
6515 
6516     @Test
testVisualDifference_differentLargeImage()6517     public void testVisualDifference_differentLargeImage() {
6518         Icon large1 = Icon.createWithResource(mContext, 1);
6519         Icon large2 = Icon.createWithResource(mContext, 2);
6520         Notification n1 = new Notification.Builder(mContext, "channel")
6521                 .setSmallIcon(1).setLargeIcon(large1).build();
6522         Notification n2 = new Notification.Builder(mContext, "channel")
6523                 .setSmallIcon(1).setLargeIcon(large2).build();
6524 
6525         NotificationRecord r1 = notificationToRecord(n1);
6526         NotificationRecord r2 = notificationToRecord(n2);
6527 
6528         assertThat(mService.isVisuallyInterruptive(r1, r2)).isTrue();
6529     }
6530 
notificationToRecord(Notification n)6531     private NotificationRecord notificationToRecord(Notification n) {
6532         return new NotificationRecord(
6533                 mContext,
6534                 new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0, n,
6535                         UserHandle.getUserHandleForUid(mUid), null, 0),
6536                 mock(NotificationChannel.class));
6537     }
6538 
6539     @Test
testHideAndUnhideNotificationsOnSuspendedPackageBroadcast()6540     public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
6541         // post 2 notification from this package
6542         final NotificationRecord notif1 = generateNotificationRecord(
6543                 mTestNotificationChannel, 1, null, true);
6544         final NotificationRecord notif2 = generateNotificationRecord(
6545                 mTestNotificationChannel, 2, null, false);
6546         mService.addNotification(notif1);
6547         mService.addNotification(notif2);
6548 
6549         // on broadcast, hide the 2 notifications
6550         simulatePackageSuspendBroadcast(true, PKG, notif1.getUid());
6551         ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
6552         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
6553         assertEquals(2, captorHide.getValue().size());
6554 
6555         // on broadcast, unhide the 2 notifications
6556         simulatePackageSuspendBroadcast(false, PKG, notif1.getUid());
6557         ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
6558         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
6559         assertEquals(2, captorUnhide.getValue().size());
6560     }
6561 
6562     @Test
testNoNotificationsHiddenOnSuspendedPackageBroadcast()6563     public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
6564         // post 2 notification from this package
6565         final NotificationRecord notif1 = generateNotificationRecord(
6566                 mTestNotificationChannel, 1, null, true);
6567         final NotificationRecord notif2 = generateNotificationRecord(
6568                 mTestNotificationChannel, 2, null, false);
6569         mService.addNotification(notif1);
6570         mService.addNotification(notif2);
6571 
6572         // on broadcast, nothing is hidden since no notifications are of package "test_package"
6573         simulatePackageSuspendBroadcast(true, "test_package", notif1.getUid());
6574         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
6575         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
6576         assertEquals(0, captor.getValue().size());
6577     }
6578 
6579     @Test
testNotificationFromDifferentUserHidden()6580     public void testNotificationFromDifferentUserHidden() {
6581         // post 2 notification from this package
6582         final NotificationRecord notif1 = generateNotificationRecord(
6583                 mTestNotificationChannel, 1, null, true);
6584         final NotificationRecord notif2 = generateNotificationRecord(
6585                 mTestNotificationChannel, 2, null, false);
6586         mService.addNotification(notif1);
6587         mService.addNotification(notif2);
6588 
6589         // on broadcast, nothing is hidden since no notifications are of user 10 with package PKG
6590         simulatePackageSuspendBroadcast(true, PKG, 10);
6591         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
6592         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
6593         assertEquals(0, captor.getValue().size());
6594     }
6595 
6596     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast()6597     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
6598         // Post 2 notifications from 2 packages
6599         NotificationRecord pkgA = new NotificationRecord(mContext,
6600                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
6601         mService.addNotification(pkgA);
6602         NotificationRecord pkgB = new NotificationRecord(mContext,
6603                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
6604         mService.addNotification(pkgB);
6605 
6606         // on broadcast, hide one of the packages
6607         simulatePackageDistractionBroadcast(
6608                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"},
6609                 new int[] {1000});
6610         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
6611         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
6612         assertEquals(1, captorHide.getValue().size());
6613         assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
6614 
6615         // on broadcast, unhide the package
6616         simulatePackageDistractionBroadcast(
6617                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"},
6618                 new int[] {1000});
6619         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
6620         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
6621         assertEquals(1, captorUnhide.getValue().size());
6622         assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
6623     }
6624 
6625     @Test
testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg()6626     public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
6627         // Post 2 notifications from 2 packages
6628         NotificationRecord pkgA = new NotificationRecord(mContext,
6629                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
6630         mService.addNotification(pkgA);
6631         NotificationRecord pkgB = new NotificationRecord(mContext,
6632                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
6633         mService.addNotification(pkgB);
6634 
6635         // on broadcast, hide one of the packages
6636         simulatePackageDistractionBroadcast(
6637                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"},
6638                 new int[] {1000, 1001});
6639         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
6640 
6641         // should be called only once.
6642         verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
6643         assertEquals(2, captorHide.getValue().size());
6644         assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
6645         assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
6646 
6647         // on broadcast, unhide the package
6648         simulatePackageDistractionBroadcast(
6649                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"},
6650                 new int[] {1000, 1001});
6651         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
6652 
6653         // should be called only once.
6654         verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
6655         assertEquals(2, captorUnhide.getValue().size());
6656         assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
6657         assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
6658     }
6659 
6660     @Test
testNoNotificationsHiddenOnDistractingPackageBroadcast()6661     public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
6662         // post notification from this package
6663         final NotificationRecord notif1 = generateNotificationRecord(
6664                 mTestNotificationChannel, 1, null, true);
6665         mService.addNotification(notif1);
6666 
6667         // on broadcast, nothing is hidden since no notifications are of package "test_package"
6668         simulatePackageDistractionBroadcast(
6669                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"},
6670                 new int[]{notif1.getUid()});
6671         ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
6672         verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
6673         assertEquals(0, captor.getValue().size());
6674     }
6675 
6676     @Test
testCanUseManagedServicesNullPkg()6677     public void testCanUseManagedServicesNullPkg() {
6678         assertEquals(true, mService.canUseManagedServices(null, 0, null));
6679     }
6680 
6681 
6682     @Test
testCanUseManagedServicesNoValidPkg()6683     public void testCanUseManagedServicesNoValidPkg() {
6684         assertEquals(true, mService.canUseManagedServices("d", 0, null));
6685     }
6686 
6687     @Test
testCanUseManagedServices_hasPermission()6688     public void testCanUseManagedServices_hasPermission() throws Exception {
6689         when(mPackageManager.checkPermission("perm", "pkg", 0))
6690                 .thenReturn(PackageManager.PERMISSION_GRANTED);
6691 
6692         assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
6693     }
6694 
6695     @Test
testCanUseManagedServices_noPermission()6696     public void testCanUseManagedServices_noPermission() throws Exception {
6697         when(mPackageManager.checkPermission("perm", "pkg", 0))
6698                 .thenReturn(PackageManager.PERMISSION_DENIED);
6699 
6700         assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
6701     }
6702 
6703     @Test
testCanUseManagedServices_permDoesNotMatter()6704     public void testCanUseManagedServices_permDoesNotMatter() {
6705         assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
6706     }
6707 
6708     @Test
testOnNotificationVisibilityChanged_triggersInterruptionUsageStat()6709     public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
6710         final NotificationRecord r = generateNotificationRecord(
6711                 mTestNotificationChannel, 1, null, true);
6712         r.setTextChanged(true);
6713         mService.addNotification(r);
6714 
6715         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
6716                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
6717                 new NotificationVisibility[]{});
6718 
6719         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
6720     }
6721 
6722     @Test
testOnNotificationVisibilityChanged_triggersVisibilityLog()6723     public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
6724         final NotificationRecord r = generateNotificationRecord(
6725                 mTestNotificationChannel, 1, null, true);
6726         r.setTextChanged(true);
6727         r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
6728         mService.addNotification(r);
6729 
6730         mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
6731                 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
6732                 new NotificationVisibility[]{});
6733 
6734         assertEquals(1, mNotificationRecordLogger.numCalls());
6735         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
6736                 mNotificationRecordLogger.event(0));
6737         assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
6738 
6739         mService.mNotificationDelegate.onNotificationVisibilityChanged(
6740                 new NotificationVisibility[]{},
6741                 new NotificationVisibility[]
6742                         {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
6743         );
6744 
6745         assertEquals(2, mNotificationRecordLogger.numCalls());
6746         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
6747                 mNotificationRecordLogger.event(1));
6748         assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
6749     }
6750 
6751     @Test
testSetNotificationsShownFromListener_triggersInterruptionUsageStat()6752     public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
6753             throws RemoteException {
6754         final NotificationRecord r = generateNotificationRecord(
6755                 mTestNotificationChannel, 1, null, true);
6756         r.setTextChanged(true);
6757         mService.addNotification(r);
6758 
6759         mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
6760 
6761         verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
6762     }
6763 
6764     @Test
testSetNotificationsShownFromListener_protectsCrossUserInformation()6765     public void testSetNotificationsShownFromListener_protectsCrossUserInformation()
6766             throws RemoteException {
6767         Notification.Builder nb = new Notification.Builder(
6768                 mContext, mTestNotificationChannel.getId())
6769                 .setContentTitle("foo")
6770                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
6771         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6772                 "tag" + System.currentTimeMillis(),  UserHandle.PER_USER_RANGE, 0,
6773                 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE),
6774                 null, 0);
6775         final NotificationRecord r =
6776                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6777         r.setTextChanged(true);
6778         mService.addNotification(r);
6779 
6780         // no security exception!
6781         mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
6782 
6783         verify(mAppUsageStats, never()).reportInterruptiveNotification(
6784                 anyString(), anyString(), anyInt());
6785     }
6786 
6787     @Test
testCancelNotificationsFromListener_protectsCrossUserInformation()6788     public void testCancelNotificationsFromListener_protectsCrossUserInformation()
6789             throws RemoteException {
6790         Notification.Builder nb = new Notification.Builder(
6791                 mContext, mTestNotificationChannel.getId())
6792                 .setContentTitle("foo")
6793                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
6794         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6795                 "tag" + System.currentTimeMillis(),  UserHandle.PER_USER_RANGE, 0,
6796                 nb.build(), UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE),
6797                 null, 0);
6798         final NotificationRecord r =
6799                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6800         r.setTextChanged(true);
6801         mService.addNotification(r);
6802 
6803         // no security exception!
6804         mBinderService.cancelNotificationsFromListener(null, new String[] {r.getKey()});
6805 
6806         waitForIdle();
6807         assertEquals(1, mService.getNotificationRecordCount());
6808     }
6809 
6810     @Test
testMaybeRecordInterruptionLocked_doesNotRecordTwice()6811     public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
6812             throws RemoteException {
6813         final NotificationRecord r = generateNotificationRecord(
6814                 mTestNotificationChannel, 1, null, true);
6815         r.setInterruptive(true);
6816         mService.addNotification(r);
6817 
6818         mService.maybeRecordInterruptionLocked(r);
6819         mService.maybeRecordInterruptionLocked(r);
6820 
6821         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
6822                 anyString(), anyString(), anyInt());
6823         verify(mHistoryManager, times(1)).addNotification(any());
6824     }
6825 
6826     @Test
testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory()6827     public void testMaybeRecordInterruptionLocked_smallIconsRequiredForHistory()
6828             throws RemoteException {
6829         final NotificationRecord r = generateNotificationRecord(
6830                 mTestNotificationChannel, 1, null, true);
6831         r.setInterruptive(true);
6832         r.getSbn().getNotification().setSmallIcon(null);
6833         mService.addNotification(r);
6834 
6835         mService.maybeRecordInterruptionLocked(r);
6836 
6837         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
6838                 anyString(), anyString(), anyInt());
6839         verify(mHistoryManager, never()).addNotification(any());
6840     }
6841 
6842     @Test
testBubble()6843     public void testBubble() throws Exception {
6844         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
6845         assertFalse(mBinderService.areBubblesAllowed(PKG));
6846         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
6847                 BUBBLE_PREFERENCE_NONE);
6848     }
6849 
6850     @Test
testUserApprovedBubblesForPackageSelected()6851     public void testUserApprovedBubblesForPackageSelected() throws Exception {
6852         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
6853         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
6854                 BUBBLE_PREFERENCE_SELECTED);
6855     }
6856 
6857     @Test
testUserApprovedBubblesForPackageAll()6858     public void testUserApprovedBubblesForPackageAll() throws Exception {
6859         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
6860         assertTrue(mBinderService.areBubblesAllowed(PKG));
6861         assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
6862                 BUBBLE_PREFERENCE_ALL);
6863     }
6864 
6865     @Test
testUserRejectsBubblesForPackage()6866     public void testUserRejectsBubblesForPackage() throws Exception {
6867         mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
6868         assertFalse(mBinderService.areBubblesAllowed(PKG));
6869     }
6870 
6871     @Test
testAreBubblesEnabled()6872     public void testAreBubblesEnabled() throws Exception {
6873         Settings.Secure.putInt(mContext.getContentResolver(),
6874                 Settings.Secure.NOTIFICATION_BUBBLES, 1);
6875         mService.mPreferencesHelper.updateBubblesEnabled();
6876         assertTrue(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid)));
6877     }
6878 
6879     @Test
testAreBubblesEnabled_false()6880     public void testAreBubblesEnabled_false() throws Exception {
6881         Settings.Secure.putInt(mContext.getContentResolver(),
6882                 Settings.Secure.NOTIFICATION_BUBBLES, 0);
6883         mService.mPreferencesHelper.updateBubblesEnabled();
6884         assertFalse(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid)));
6885     }
6886 
6887     @Test
testAreBubblesEnabled_exception()6888     public void testAreBubblesEnabled_exception() throws Exception {
6889         try {
6890             assertTrue(mBinderService.areBubblesEnabled(
6891                     UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE)));
6892             fail("Cannot call cross user without permission");
6893         } catch (SecurityException e) {
6894             // pass
6895         }
6896         // cross user, with permission, no problem
6897         enableInteractAcrossUsers();
6898         assertTrue(mBinderService.areBubblesEnabled(
6899                 UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE)));
6900     }
6901 
6902     @Test
testIsCallerInstantApp_primaryUser()6903     public void testIsCallerInstantApp_primaryUser() throws Exception {
6904         ApplicationInfo info = new ApplicationInfo();
6905         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
6906         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
6907         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
6908 
6909         assertTrue(mService.isCallerInstantApp(45770, 0));
6910 
6911         info.privateFlags = 0;
6912         assertFalse(mService.isCallerInstantApp(575370, 0));
6913     }
6914 
6915     @Test
testIsCallerInstantApp_secondaryUser()6916     public void testIsCallerInstantApp_secondaryUser() throws Exception {
6917         ApplicationInfo info = new ApplicationInfo();
6918         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
6919         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info);
6920         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null);
6921         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
6922 
6923         assertTrue(mService.isCallerInstantApp(68638450, 10));
6924     }
6925 
6926     @Test
testIsCallerInstantApp_userAllNotification()6927     public void testIsCallerInstantApp_userAllNotification() throws Exception {
6928         ApplicationInfo info = new ApplicationInfo();
6929         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
6930         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(USER_SYSTEM)))
6931                 .thenReturn(info);
6932         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
6933 
6934         assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
6935 
6936         info.privateFlags = 0;
6937         assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
6938     }
6939 
6940     @Test
testResolveNotificationUid_sameApp_nonSystemUser()6941     public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
6942         ApplicationInfo info = new ApplicationInfo();
6943         info.uid = Binder.getCallingUid();
6944         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(10))).thenReturn(info);
6945         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(null);
6946 
6947         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
6948 
6949         assertEquals(info.uid, actualUid);
6950     }
6951 
6952     @Test
testResolveNotificationUid_sameApp()6953     public void testResolveNotificationUid_sameApp() throws Exception {
6954         ApplicationInfo info = new ApplicationInfo();
6955         info.uid = Binder.getCallingUid();
6956         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
6957 
6958         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
6959 
6960         assertEquals(info.uid, actualUid);
6961     }
6962 
6963     @Test
testResolveNotificationUid_sameAppDiffPackage()6964     public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
6965         ApplicationInfo info = new ApplicationInfo();
6966         info.uid = Binder.getCallingUid();
6967         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), eq(0))).thenReturn(info);
6968 
6969         int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
6970 
6971         assertEquals(info.uid, actualUid);
6972     }
6973 
6974     @Test
testResolveNotificationUid_sameAppWrongUid()6975     public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
6976         ApplicationInfo info = new ApplicationInfo();
6977         info.uid = 1356347;
6978         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(info);
6979 
6980         try {
6981             mService.resolveNotificationUid("caller", "caller", 9, 0);
6982             fail("Incorrect uid didn't throw security exception");
6983         } catch (SecurityException e) {
6984             // yay
6985         }
6986     }
6987 
6988     @Test
testResolveNotificationUid_delegateAllowed()6989     public void testResolveNotificationUid_delegateAllowed() throws Exception {
6990         int expectedUid = 123;
6991 
6992         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
6993         mService.setPreferencesHelper(mPreferencesHelper);
6994         when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
6995                 .thenReturn(true);
6996 
6997         assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
6998     }
6999 
7000     @Test
testResolveNotificationUid_androidAllowed()7001     public void testResolveNotificationUid_androidAllowed() throws Exception {
7002         int expectedUid = 123;
7003 
7004         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
7005         // no delegate
7006 
7007         assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
7008     }
7009 
7010     @Test
testPostFromAndroidForNonExistentPackage()7011     public void testPostFromAndroidForNonExistentPackage() throws Exception {
7012         final String notReal = "NOT REAL";
7013         when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
7014                 PackageManager.NameNotFoundException.class);
7015         ApplicationInfo ai = new ApplicationInfo();
7016         ai.uid = -1;
7017         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai);
7018 
7019         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
7020         try {
7021             mInternalService.enqueueNotification(notReal, "android", 0, 0,
7022                     "testPostFromAndroidForNonExistentPackage",
7023                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
7024             fail("can't post notifications for nonexistent packages, even if you exist");
7025         } catch (SecurityException e) {
7026             // yay
7027         }
7028     }
7029 
7030     @Test
testCancelFromAndroidForNonExistentPackage()7031     public void testCancelFromAndroidForNonExistentPackage() throws Exception {
7032         final String notReal = "NOT REAL";
7033         when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
7034                 PackageManager.NameNotFoundException.class);
7035         ApplicationInfo ai = new ApplicationInfo();
7036         ai.uid = -1;
7037         when(mPackageManager.getApplicationInfo(anyString(), anyLong(), anyInt())).thenReturn(ai);
7038 
7039         // unlike the post case, ignore instead of throwing
7040         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
7041 
7042         mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
7043                 sbn.getId(), sbn.getUserId());
7044     }
7045 
7046     @Test
testResolveNotificationUid_delegateNotAllowed()7047     public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
7048         when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
7049         // no delegate
7050 
7051         try {
7052             mService.resolveNotificationUid("caller", "target", 9, 0);
7053             fail("Incorrect uid didn't throw security exception");
7054         } catch (SecurityException e) {
7055             // yay
7056         }
7057     }
7058 
7059     @Test
testRemoveForegroundServiceFlagFromNotification_enqueued()7060     public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
7061         when(mAmi.applyForegroundServiceNotification(
7062                 any(), anyString(), anyInt(), anyString(), anyInt()))
7063                 .thenReturn(SHOW_IMMEDIATELY);
7064         Notification n = new Notification.Builder(mContext, "").build();
7065         n.flags |= FLAG_FOREGROUND_SERVICE;
7066 
7067         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
7068                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7069         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7070 
7071         mService.addEnqueuedNotification(r);
7072 
7073         mInternalService.removeForegroundServiceFlagFromNotification(
7074                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7075 
7076         waitForIdle();
7077 
7078         verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
7079     }
7080 
7081     @Test
testRemoveForegroundServiceFlagFromNotification_posted()7082     public void testRemoveForegroundServiceFlagFromNotification_posted() {
7083         when(mAmi.applyForegroundServiceNotification(
7084                 any(), anyString(), anyInt(), anyString(), anyInt()))
7085                 .thenReturn(SHOW_IMMEDIATELY);
7086         Notification n = new Notification.Builder(mContext, "").build();
7087         n.flags |= FLAG_FOREGROUND_SERVICE;
7088 
7089         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
7090                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7091         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7092 
7093         mService.addNotification(r);
7094 
7095         mInternalService.removeForegroundServiceFlagFromNotification(
7096                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7097 
7098         waitForIdle();
7099 
7100         ArgumentCaptor<NotificationRecord> captor =
7101                 ArgumentCaptor.forClass(NotificationRecord.class);
7102         verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
7103 
7104         assertEquals(0, captor.getValue().getNotification().flags);
7105     }
7106 
7107     @Test
testCannotRemoveForegroundFlagWhenOverLimit_enqueued()7108     public void testCannotRemoveForegroundFlagWhenOverLimit_enqueued() {
7109         when(mAmi.applyForegroundServiceNotification(
7110                 any(), anyString(), anyInt(), anyString(), anyInt()))
7111                 .thenReturn(SHOW_IMMEDIATELY);
7112         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7113             Notification n = new Notification.Builder(mContext, "").build();
7114             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
7115                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
7116             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7117             mService.addEnqueuedNotification(r);
7118         }
7119         Notification n = new Notification.Builder(mContext, "").build();
7120         n.flags |= FLAG_FOREGROUND_SERVICE;
7121 
7122         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
7123                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
7124                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7125         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7126 
7127         mService.addEnqueuedNotification(r);
7128 
7129         mInternalService.removeForegroundServiceFlagFromNotification(
7130                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7131 
7132         waitForIdle();
7133 
7134         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
7135                 mService.getNotificationRecordCount());
7136     }
7137 
7138     @Test
testCannotRemoveForegroundFlagWhenOverLimit_posted()7139     public void testCannotRemoveForegroundFlagWhenOverLimit_posted() {
7140         when(mAmi.applyForegroundServiceNotification(
7141                 any(), anyString(), anyInt(), anyString(), anyInt()))
7142                 .thenReturn(SHOW_IMMEDIATELY);
7143         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7144             Notification n = new Notification.Builder(mContext, "").build();
7145             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
7146                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
7147             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7148             mService.addNotification(r);
7149         }
7150         Notification n = new Notification.Builder(mContext, "").build();
7151         n.flags |= FLAG_FOREGROUND_SERVICE;
7152 
7153         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
7154                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
7155                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
7156         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7157 
7158         mService.addNotification(r);
7159 
7160         mInternalService.removeForegroundServiceFlagFromNotification(
7161                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
7162 
7163         waitForIdle();
7164 
7165         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
7166                 mService.getNotificationRecordCount());
7167     }
7168 
7169     @Test
testAllowForegroundCustomToasts()7170     public void testAllowForegroundCustomToasts() throws Exception {
7171         final String testPackage = "testPackageName";
7172         assertEquals(0, mService.mToastQueue.size());
7173         mService.isSystemUid = false;
7174         mService.isSystemAppId = false;
7175         setToastRateIsWithinQuota(true);
7176         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7177 
7178         // package is not suspended
7179         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7180                 .thenReturn(false);
7181 
7182         // notifications from this package are blocked by the user
7183         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
7184 
7185         setAppInForegroundForToasts(mUid, true);
7186 
7187         // enqueue toast -> toast should still enqueue
7188         enqueueToast(testPackage, new TestableToastCallback());
7189         assertEquals(1, mService.mToastQueue.size());
7190     }
7191 
7192     @Test
testDisallowBackgroundCustomToasts()7193     public void testDisallowBackgroundCustomToasts() throws Exception {
7194         final String testPackage = "testPackageName";
7195         assertEquals(0, mService.mToastQueue.size());
7196         mService.isSystemUid = false;
7197         mService.isSystemAppId = false;
7198         setToastRateIsWithinQuota(true);
7199         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7200 
7201         // package is not suspended
7202         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7203                 .thenReturn(false);
7204 
7205         setAppInForegroundForToasts(mUid, false);
7206 
7207         // enqueue toast -> no toasts enqueued
7208         enqueueToast(testPackage, new TestableToastCallback());
7209         assertEquals(0, mService.mToastQueue.size());
7210     }
7211 
7212     @Test
testDontCallShowToastAgainOnTheSameCustomToast()7213     public void testDontCallShowToastAgainOnTheSameCustomToast() throws Exception {
7214         final String testPackage = "testPackageName";
7215         assertEquals(0, mService.mToastQueue.size());
7216         mService.isSystemUid = false;
7217         mService.isSystemAppId = false;
7218         setToastRateIsWithinQuota(true);
7219         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7220 
7221         // package is not suspended
7222         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7223                 .thenReturn(false);
7224 
7225         setAppInForegroundForToasts(mUid, true);
7226 
7227         Binder token = new Binder();
7228         ITransientNotification callback = mock(ITransientNotification.class);
7229         INotificationManager nmService = (INotificationManager) mService.mService;
7230 
7231         // first time trying to show the toast, showToast gets called
7232         enqueueToast(nmService, testPackage, token, callback);
7233         verify(callback, times(1)).show(any());
7234 
7235         // second time trying to show the same toast, showToast isn't called again (total number of
7236         // invocations stays at one)
7237         enqueueToast(nmService, testPackage, token, callback);
7238         verify(callback, times(1)).show(any());
7239     }
7240 
7241     @Test
testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground()7242     public void testToastRateLimiterWontPreventShowCallForCustomToastWhenInForeground()
7243             throws Exception {
7244         final String testPackage = "testPackageName";
7245         assertEquals(0, mService.mToastQueue.size());
7246         mService.isSystemUid = false;
7247         mService.isSystemAppId = false;
7248         setToastRateIsWithinQuota(false); // rate limit reached
7249         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7250 
7251         // package is not suspended
7252         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7253                 .thenReturn(false);
7254 
7255         setAppInForegroundForToasts(mUid, true);
7256 
7257         Binder token = new Binder();
7258         ITransientNotification callback = mock(ITransientNotification.class);
7259         INotificationManager nmService = (INotificationManager) mService.mService;
7260 
7261         enqueueToast(nmService, testPackage, token, callback);
7262         verify(callback, times(1)).show(any());
7263     }
7264 
7265     @Test
testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()7266     public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()
7267             throws Exception {
7268         final String testPackage = "testPackageName";
7269         assertEquals(0, mService.mToastQueue.size());
7270         mService.isSystemUid = false;
7271         mService.isSystemAppId = false;
7272         setToastRateIsWithinQuota(true);
7273         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7274 
7275         // package is not suspended
7276         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7277                 .thenReturn(false);
7278 
7279         setAppInForegroundForToasts(mUid, true);
7280 
7281         Binder token1 = new Binder();
7282         Binder token2 = new Binder();
7283         ITransientNotification callback1 = mock(ITransientNotification.class);
7284         ITransientNotification callback2 = mock(ITransientNotification.class);
7285         INotificationManager nmService = (INotificationManager) mService.mService;
7286 
7287         enqueueToast(nmService, testPackage, token1, callback1);
7288         enqueueToast(nmService, testPackage, token2, callback2);
7289 
7290         assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued.
7291         verify(callback1, times(1)).show(any()); // First toast shown.
7292 
7293         setAppInForegroundForToasts(mUid, false);
7294 
7295         mService.cancelToastLocked(0); // Remove the first toast, and show next.
7296 
7297         assertEquals(0, mService.mToastQueue.size()); // Both toasts processed.
7298         verify(callback2, never()).show(any()); // Second toast was never shown.
7299     }
7300 
7301     @Test
testAllowForegroundTextToasts()7302     public void testAllowForegroundTextToasts() throws Exception {
7303         final String testPackage = "testPackageName";
7304         assertEquals(0, mService.mToastQueue.size());
7305         mService.isSystemUid = false;
7306         mService.isSystemAppId = false;
7307         setToastRateIsWithinQuota(true);
7308         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7309 
7310         // package is not suspended
7311         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7312                 .thenReturn(false);
7313 
7314         setAppInForegroundForToasts(mUid, true);
7315 
7316         // enqueue toast -> toast should still enqueue
7317         enqueueTextToast(testPackage, "Text");
7318         assertEquals(1, mService.mToastQueue.size());
7319     }
7320 
7321     @Test
testAllowBackgroundTextToasts()7322     public void testAllowBackgroundTextToasts() throws Exception {
7323         final String testPackage = "testPackageName";
7324         assertEquals(0, mService.mToastQueue.size());
7325         mService.isSystemUid = false;
7326         mService.isSystemAppId = false;
7327         setToastRateIsWithinQuota(true);
7328         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7329 
7330         // package is not suspended
7331         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7332                 .thenReturn(false);
7333 
7334         setAppInForegroundForToasts(mUid, false);
7335 
7336         // enqueue toast -> toast should still enqueue
7337         enqueueTextToast(testPackage, "Text");
7338         assertEquals(1, mService.mToastQueue.size());
7339     }
7340 
7341     @Test
testDontCallShowToastAgainOnTheSameTextToast()7342     public void testDontCallShowToastAgainOnTheSameTextToast() throws Exception {
7343         final String testPackage = "testPackageName";
7344         assertEquals(0, mService.mToastQueue.size());
7345         mService.isSystemUid = false;
7346         mService.isSystemAppId = false;
7347         setToastRateIsWithinQuota(true);
7348         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7349 
7350         // package is not suspended
7351         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7352                 .thenReturn(false);
7353 
7354         setAppInForegroundForToasts(mUid, true);
7355 
7356         Binder token = new Binder();
7357         INotificationManager nmService = (INotificationManager) mService.mService;
7358 
7359         // first time trying to show the toast, showToast gets called
7360         enqueueTextToast(testPackage, "Text");
7361         verify(mStatusBar, times(1))
7362                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7363 
7364         // second time trying to show the same toast, showToast isn't called again (total number of
7365         // invocations stays at one)
7366         enqueueTextToast(testPackage, "Text");
7367         verify(mStatusBar, times(1))
7368                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7369     }
7370 
7371     @Test
testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground()7372     public void testToastRateLimiterCanPreventShowCallForTextToast_whenInBackground()
7373             throws Exception {
7374         final String testPackage = "testPackageName";
7375         assertEquals(0, mService.mToastQueue.size());
7376         mService.isSystemUid = false;
7377         mService.isSystemAppId = false;
7378         setToastRateIsWithinQuota(false); // rate limit reached
7379         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7380         setAppInForegroundForToasts(mUid, false);
7381 
7382         // package is not suspended
7383         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7384                 .thenReturn(false);
7385 
7386         Binder token = new Binder();
7387         INotificationManager nmService = (INotificationManager) mService.mService;
7388 
7389         enqueueTextToast(testPackage, "Text");
7390         verify(mStatusBar, times(0))
7391                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7392     }
7393 
7394     @Test
testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground()7395     public void testToastRateLimiterWontPreventShowCallForTextToast_whenInForeground()
7396             throws Exception {
7397         final String testPackage = "testPackageName";
7398         assertEquals(0, mService.mToastQueue.size());
7399         mService.isSystemUid = false;
7400         mService.isSystemAppId = false;
7401         setToastRateIsWithinQuota(false); // rate limit reached
7402         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7403         setAppInForegroundForToasts(mUid, true);
7404 
7405         // package is not suspended
7406         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7407                 .thenReturn(false);
7408 
7409         Binder token = new Binder();
7410         INotificationManager nmService = (INotificationManager) mService.mService;
7411 
7412         enqueueTextToast(testPackage, "Text");
7413         verify(mStatusBar, times(1))
7414                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7415     }
7416 
7417     @Test
testTextToastRateLimiterAllowsLimitAvoidanceWithPermission()7418     public void testTextToastRateLimiterAllowsLimitAvoidanceWithPermission() throws Exception {
7419         final String testPackage = "testPackageName";
7420         assertEquals(0, mService.mToastQueue.size());
7421         mService.isSystemUid = false;
7422         mService.isSystemAppId = false;
7423         setToastRateIsWithinQuota(false); // rate limit reached
7424         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, true);
7425         setAppInForegroundForToasts(mUid, false);
7426 
7427         // package is not suspended
7428         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7429                 .thenReturn(false);
7430 
7431         Binder token = new Binder();
7432         INotificationManager nmService = (INotificationManager) mService.mService;
7433 
7434         enqueueTextToast(testPackage, "Text");
7435         verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
7436                 anyInt());
7437     }
7438 
7439     @Test
testRateLimitedToasts_windowsRemoved()7440     public void testRateLimitedToasts_windowsRemoved() throws Exception {
7441         final String testPackage = "testPackageName";
7442         assertEquals(0, mService.mToastQueue.size());
7443         mService.isSystemUid = false;
7444         mService.isSystemAppId = false;
7445         setToastRateIsWithinQuota(false); // rate limit reached
7446         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7447         setAppInForegroundForToasts(mUid, false);
7448 
7449         // package is not suspended
7450         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7451                 .thenReturn(false);
7452 
7453         Binder token = new Binder();
7454         INotificationManager nmService = (INotificationManager) mService.mService;
7455 
7456         enqueueTextToast(testPackage, "Text");
7457 
7458         // window token was added when enqueued
7459         ArgumentCaptor<Binder> binderCaptor =
7460                 ArgumentCaptor.forClass(Binder.class);
7461         verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(),
7462                 eq(TYPE_TOAST), anyInt(), eq(null));
7463 
7464         // but never shown
7465         verify(mStatusBar, times(0))
7466                 .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(), anyInt());
7467 
7468         // and removed when rate limited
7469         verify(mWindowManagerInternal)
7470                 .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt());
7471     }
7472 
7473     @Test
backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast()7474     public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws
7475             Exception {
7476         final String testPackage = "testPackageName";
7477         assertEquals(0, mService.mToastQueue.size());
7478         mService.isSystemUid = true;
7479         setToastRateIsWithinQuota(true);
7480         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7481 
7482         // package is not suspended
7483         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7484                 .thenReturn(false);
7485 
7486         // notifications from this package are blocked by the user
7487         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
7488 
7489         setAppInForegroundForToasts(mUid, false);
7490 
7491         // enqueue toast -> toast should still enqueue
7492         enqueueToast(testPackage, new TestableToastCallback());
7493         assertEquals(1, mService.mToastQueue.size());
7494         verify(mAm).setProcessImportant(any(), anyInt(), eq(true), any());
7495     }
7496 
7497     @Test
foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7498     public void foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws
7499             Exception {
7500         final String testPackage = "testPackageName";
7501         assertEquals(0, mService.mToastQueue.size());
7502         mService.isSystemUid = false;
7503         mService.isSystemAppId = false;
7504         setToastRateIsWithinQuota(true);
7505         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7506 
7507         // package is not suspended
7508         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7509                 .thenReturn(false);
7510 
7511         setAppInForegroundForToasts(mUid, true);
7512 
7513         // enqueue toast -> toast should still enqueue
7514         enqueueTextToast(testPackage, "Text");
7515         assertEquals(1, mService.mToastQueue.size());
7516         verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
7517     }
7518 
7519     @Test
backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast()7520     public void backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws
7521             Exception {
7522         final String testPackage = "testPackageName";
7523         assertEquals(0, mService.mToastQueue.size());
7524         mService.isSystemUid = false;
7525         mService.isSystemAppId = false;
7526         setToastRateIsWithinQuota(true);
7527         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7528 
7529         // package is not suspended
7530         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7531                 .thenReturn(false);
7532 
7533         setAppInForegroundForToasts(mUid, false);
7534 
7535         // enqueue toast -> toast should still enqueue
7536         enqueueTextToast(testPackage, "Text");
7537         assertEquals(1, mService.mToastQueue.size());
7538         verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
7539     }
7540 
7541     @Test
testTextToastsCallStatusBar()7542     public void testTextToastsCallStatusBar() throws Exception {
7543         allowTestPackageToToast();
7544 
7545         // enqueue toast -> no toasts enqueued
7546         enqueueTextToast(TEST_PACKAGE, "Text");
7547 
7548         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
7549     }
7550 
7551     @Test
testTextToastsCallStatusBar_nonUiContext_defaultDisplay()7552     public void testTextToastsCallStatusBar_nonUiContext_defaultDisplay()
7553             throws Exception {
7554         allowTestPackageToToast();
7555 
7556         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY);
7557 
7558         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
7559     }
7560 
7561     @Test
testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()7562     public void testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()
7563             throws Exception {
7564         allowTestPackageToToast();
7565         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7566 
7567         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID);
7568 
7569         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7570     }
7571 
7572     @Test
testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay()7573     public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_defaultDisplay()
7574             throws Exception {
7575         mockIsVisibleBackgroundUsersSupported(true);
7576         mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID);
7577         allowTestPackageToToast();
7578 
7579         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, DEFAULT_DISPLAY);
7580 
7581         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
7582 
7583     }
7584 
7585     @Test
testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()7586     public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()
7587             throws Exception {
7588         mockIsVisibleBackgroundUsersSupported(true);
7589         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7590         mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used
7591         allowTestPackageToToast();
7592 
7593         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ true, SECONDARY_DISPLAY_ID);
7594 
7595         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7596     }
7597 
7598     @Test
testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay()7599     public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_defaultDisplay()
7600             throws Exception {
7601         mockIsVisibleBackgroundUsersSupported(true);
7602         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7603         mockDisplayAssignedToUser(SECONDARY_DISPLAY_ID);
7604         allowTestPackageToToast();
7605 
7606         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, DEFAULT_DISPLAY);
7607 
7608         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7609     }
7610 
7611     @Test
testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()7612     public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()
7613             throws Exception {
7614         mockIsVisibleBackgroundUsersSupported(true);
7615         mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
7616         mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used
7617         allowTestPackageToToast();
7618 
7619         enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID);
7620 
7621         verifyToastShownForTestPackage("Text", SECONDARY_DISPLAY_ID);
7622     }
7623 
7624     @Test
testTextToastsCallStatusBar_userNotVisibleOnDisplay()7625     public void testTextToastsCallStatusBar_userNotVisibleOnDisplay() throws Exception {
7626         final String testPackage = "testPackageName";
7627         assertEquals(0, mService.mToastQueue.size());
7628         mService.isSystemUid = false;
7629         mService.isSystemAppId = false;
7630         setToastRateIsWithinQuota(true);
7631         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7632         mockIsUserVisible(DEFAULT_DISPLAY, false);
7633 
7634         // package is not suspended
7635         when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
7636                 .thenReturn(false);
7637 
7638         // enqueue toast -> no toasts enqueued
7639         enqueueTextToast(testPackage, "Text");
7640         verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
7641                 anyInt());
7642         assertEquals(0, mService.mToastQueue.size());
7643     }
7644 
7645     @Test
testDisallowToastsFromSuspendedPackages()7646     public void testDisallowToastsFromSuspendedPackages() throws Exception {
7647         final String testPackage = "testPackageName";
7648         assertEquals(0, mService.mToastQueue.size());
7649         mService.isSystemUid = false;
7650         mService.isSystemAppId = false;
7651         setToastRateIsWithinQuota(true);
7652         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7653 
7654         // package is suspended
7655         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7656                 .thenReturn(true);
7657 
7658         // notifications from this package are NOT blocked by the user
7659         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
7660 
7661         // enqueue toast -> no toasts enqueued
7662         enqueueToast(testPackage, new TestableToastCallback());
7663         verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
7664                 anyInt());
7665         assertEquals(0, mService.mToastQueue.size());
7666     }
7667 
7668     @Test
testDisallowToastsFromBlockedApps()7669     public void testDisallowToastsFromBlockedApps() throws Exception {
7670         final String testPackage = "testPackageName";
7671         assertEquals(0, mService.mToastQueue.size());
7672         mService.isSystemUid = false;
7673         mService.isSystemAppId = false;
7674         setToastRateIsWithinQuota(true);
7675         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7676 
7677         // package is not suspended
7678         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7679                 .thenReturn(false);
7680 
7681         // notifications from this package are blocked by the user
7682         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
7683 
7684         setAppInForegroundForToasts(mUid, false);
7685 
7686         // enqueue toast -> no toasts enqueued
7687         enqueueToast(testPackage, new TestableToastCallback());
7688         assertEquals(0, mService.mToastQueue.size());
7689     }
7690 
7691     @Test
testAlwaysAllowSystemToasts()7692     public void testAlwaysAllowSystemToasts() throws Exception {
7693         final String testPackage = "testPackageName";
7694         assertEquals(0, mService.mToastQueue.size());
7695         mService.isSystemUid = true;
7696         setToastRateIsWithinQuota(true);
7697         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7698 
7699         // package is suspended
7700         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7701                 .thenReturn(true);
7702 
7703         // notifications from this package ARE blocked by the user
7704         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
7705 
7706         setAppInForegroundForToasts(mUid, false);
7707 
7708         // enqueue toast -> system toast can still be enqueued
7709         enqueueToast(testPackage, new TestableToastCallback());
7710         assertEquals(1, mService.mToastQueue.size());
7711     }
7712 
7713     @Test
testLimitNumberOfQueuedToastsFromPackage()7714     public void testLimitNumberOfQueuedToastsFromPackage() throws Exception {
7715         final String testPackage = "testPackageName";
7716         assertEquals(0, mService.mToastQueue.size());
7717         mService.isSystemUid = false;
7718         mService.isSystemAppId = false;
7719         setToastRateIsWithinQuota(true);
7720         setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
7721 
7722         // package is not suspended
7723         when(mPackageManager.isPackageSuspendedForUser(testPackage, mUserId))
7724                 .thenReturn(false);
7725 
7726         INotificationManager nmService = (INotificationManager) mService.mService;
7727 
7728         // Trying to quickly enqueue more toast than allowed.
7729         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS + 1; i++) {
7730             enqueueTextToast(testPackage, "Text");
7731         }
7732         // Only allowed number enqueued, rest ignored.
7733         assertEquals(NotificationManagerService.MAX_PACKAGE_TOASTS, mService.mToastQueue.size());
7734     }
7735 
setAppInForegroundForToasts(int uid, boolean inForeground)7736     private void setAppInForegroundForToasts(int uid, boolean inForeground) {
7737         int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
7738         when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
7739         when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
7740     }
7741 
setToastRateIsWithinQuota(boolean isWithinQuota)7742     private void setToastRateIsWithinQuota(boolean isWithinQuota) {
7743         when(mToastRateLimiter.isWithinQuota(
7744                 anyInt(),
7745                 anyString(),
7746                 eq(NotificationManagerService.TOAST_QUOTA_TAG)))
7747                 .thenReturn(isWithinQuota);
7748     }
7749 
setIfPackageHasPermissionToAvoidToastRateLimiting( String pkg, boolean hasPermission)7750     private void setIfPackageHasPermissionToAvoidToastRateLimiting(
7751             String pkg, boolean hasPermission) throws Exception {
7752         when(mPackageManager.checkPermission(android.Manifest.permission.UNLIMITED_TOASTS,
7753                 pkg, mUserId))
7754                 .thenReturn(hasPermission ? PERMISSION_GRANTED : PERMISSION_DENIED);
7755     }
7756 
7757     @Test
testOnPanelRevealedAndHidden()7758     public void testOnPanelRevealedAndHidden() {
7759         int items = 5;
7760         mService.mNotificationDelegate.onPanelRevealed(false, items);
7761         verify(mAssistants, times(1)).onPanelRevealed(eq(items));
7762 
7763         mService.mNotificationDelegate.onPanelHidden();
7764         verify(mAssistants, times(1)).onPanelHidden();
7765 
7766         assertEquals(2, mNotificationRecordLogger.numCalls());
7767         assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
7768                 mNotificationRecordLogger.event(0));
7769         assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
7770                 mNotificationRecordLogger.event(1));
7771     }
7772 
7773     @Test
testOnNotificationSmartReplySent()7774     public void testOnNotificationSmartReplySent() {
7775         final int replyIndex = 2;
7776         final String reply = "Hello";
7777         final boolean modifiedBeforeSending = true;
7778         final boolean generatedByAssistant = true;
7779 
7780         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7781         r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
7782         mService.addNotification(r);
7783 
7784         mService.mNotificationDelegate.onNotificationSmartReplySent(
7785                 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
7786                 modifiedBeforeSending);
7787         verify(mAssistants).notifyAssistantSuggestedReplySent(
7788                 eq(r.getSbn()), eq(FLAG_FILTER_TYPE_ALERTING), eq(reply), eq(generatedByAssistant));
7789         assertEquals(1, mNotificationRecordLogger.numCalls());
7790         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
7791                 mNotificationRecordLogger.event(0));
7792     }
7793 
7794     @Test
testOnNotificationActionClick()7795     public void testOnNotificationActionClick() {
7796         final int actionIndex = 2;
7797         final Notification.Action action =
7798                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
7799                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
7800         final boolean generatedByAssistant = false;
7801 
7802         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7803         mService.addNotification(r);
7804 
7805         NotificationVisibility notificationVisibility =
7806                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
7807         mService.mNotificationDelegate.onNotificationActionClick(
7808                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
7809                 generatedByAssistant);
7810         verify(mAssistants).notifyAssistantActionClicked(
7811                 eq(r), eq(action), eq(generatedByAssistant));
7812 
7813         assertEquals(1, mNotificationRecordLogger.numCalls());
7814         assertEquals(
7815                 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2,
7816                 mNotificationRecordLogger.event(0));
7817     }
7818 
7819     @Test
testOnAssistantNotificationActionClick()7820     public void testOnAssistantNotificationActionClick() {
7821         final int actionIndex = 1;
7822         final Notification.Action action =
7823                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
7824                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
7825         final boolean generatedByAssistant = true;
7826 
7827         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7828         mService.addNotification(r);
7829 
7830         NotificationVisibility notificationVisibility =
7831                 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
7832         mService.mNotificationDelegate.onNotificationActionClick(
7833                 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
7834                 generatedByAssistant);
7835         verify(mAssistants).notifyAssistantActionClicked(
7836                 eq(r), eq(action), eq(generatedByAssistant));
7837 
7838         assertEquals(1, mNotificationRecordLogger.numCalls());
7839         assertEquals(
7840                 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1,
7841                 mNotificationRecordLogger.event(0));
7842     }
7843 
7844     @Test
testLogSmartSuggestionsVisible_triggerOnExpandAndVisible()7845     public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
7846         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7847         mService.addNotification(r);
7848 
7849         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
7850                 NOTIFICATION_LOCATION_UNKNOWN);
7851         NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
7852                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
7853         };
7854         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
7855                 new NotificationVisibility[0]);
7856 
7857         assertEquals(1, mService.countLogSmartSuggestionsVisible);
7858     }
7859 
7860     @Test
testLogSmartSuggestionsVisible_noTriggerOnExpand()7861     public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
7862         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7863         mService.addNotification(r);
7864 
7865         mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
7866                 NOTIFICATION_LOCATION_UNKNOWN);
7867 
7868         assertEquals(0, mService.countLogSmartSuggestionsVisible);
7869     }
7870 
7871     @Test
testLogSmartSuggestionsVisible_noTriggerOnVisible()7872     public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
7873         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7874         mService.addNotification(r);
7875 
7876         NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
7877                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
7878         };
7879         mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
7880                 new NotificationVisibility[0]);
7881 
7882         assertEquals(0, mService.countLogSmartSuggestionsVisible);
7883     }
7884 
7885     @Test
testReportSeen_delegated()7886     public void testReportSeen_delegated() {
7887         Notification.Builder nb =
7888                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
7889                         .setContentTitle("foo")
7890                         .setSmallIcon(android.R.drawable.sym_def_app_icon);
7891 
7892         StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
7893                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
7894         NotificationRecord r =  new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7895 
7896         mService.reportSeen(r);
7897         verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
7898 
7899     }
7900 
7901     @Test
testReportSeen_notDelegated()7902     public void testReportSeen_notDelegated() {
7903         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7904 
7905         mService.reportSeen(r);
7906         verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
7907     }
7908 
7909     @Test
testNotificationStats_notificationError()7910     public void testNotificationStats_notificationError() {
7911         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
7912         mService.addNotification(r);
7913 
7914         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
7915                 r.getSbn().getTag(), mUid, 0,
7916                 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
7917                 UserHandle.getUserHandleForUid(mUid), null, 0);
7918         NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7919         mService.addEnqueuedNotification(update);
7920         assertNull(update.getSbn().getNotification().getSmallIcon());
7921 
7922         NotificationManagerService.PostNotificationRunnable runnable =
7923                 mService.new PostNotificationRunnable(update.getKey(), r.getSbn().getPackageName(),
7924                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
7925         runnable.run();
7926         waitForIdle();
7927 
7928         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
7929         verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
7930         assertNotNull(captor.getValue());
7931     }
7932 
7933     @Test
testCanNotifyAsUser_crossUser()7934     public void testCanNotifyAsUser_crossUser() throws Exception {
7935         // same user no problem
7936         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
7937 
7938         // cross user, no permission, problem
7939         try {
7940             mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
7941             fail("Should not be callable cross user without cross user permission");
7942         } catch (SecurityException e) {
7943             // good
7944         }
7945 
7946         // cross user, with permission, no problem
7947         enableInteractAcrossUsers();
7948         mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
7949     }
7950 
7951     @Test
testGetNotificationChannels_crossUser()7952     public void testGetNotificationChannels_crossUser() throws Exception {
7953         // same user no problem
7954         mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
7955 
7956         // cross user, no permission, problem
7957         try {
7958             mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
7959             fail("Should not be callable cross user without cross user permission");
7960         } catch (SecurityException e) {
7961             // good
7962         }
7963 
7964         // cross user, with permission, no problem
7965         enableInteractAcrossUsers();
7966         mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
7967     }
7968 
7969     @Test
setDefaultAssistantForUser_fromConfigXml()7970     public void setDefaultAssistantForUser_fromConfigXml() {
7971         clearDeviceConfig();
7972         ComponentName xmlConfig = new ComponentName("config", "xml");
7973         ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
7974         when(mResources
7975                 .getString(
7976                         com.android.internal.R.string.config_defaultAssistantAccessComponent))
7977                 .thenReturn(xmlConfig.flattenToString());
7978         when(mContext.getResources()).thenReturn(mResources);
7979         when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
7980                 .thenReturn(components);
7981         when(mAssistants.getDefaultComponents())
7982                 .thenReturn(components);
7983         mService.setNotificationAssistantAccessGrantedCallback(
7984                 mNotificationAssistantAccessGrantedCallback);
7985 
7986 
7987         mService.setDefaultAssistantForUser(0);
7988 
7989         verify(mNotificationAssistantAccessGrantedCallback)
7990                 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false));
7991     }
7992 
7993     @Test
setDefaultAssistantForUser_fromDeviceConfig()7994     public void setDefaultAssistantForUser_fromDeviceConfig() {
7995         ComponentName xmlConfig = new ComponentName("xml", "config");
7996         ComponentName deviceConfig = new ComponentName("device", "config");
7997         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
7998         when(mResources
7999                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
8000                 .thenReturn(xmlConfig.flattenToString());
8001         when(mContext.getResources()).thenReturn(mResources);
8002         when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
8003                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
8004         when(mAssistants.getDefaultComponents())
8005                 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
8006         mService.setNotificationAssistantAccessGrantedCallback(
8007                 mNotificationAssistantAccessGrantedCallback);
8008 
8009         mService.setDefaultAssistantForUser(0);
8010 
8011         verify(mNotificationAssistantAccessGrantedCallback)
8012                 .onGranted(eq(deviceConfig), eq(0), eq(true), eq(false));
8013     }
8014 
8015     @Test
setDefaultAssistantForUser_deviceConfigInvalid()8016     public void setDefaultAssistantForUser_deviceConfigInvalid() {
8017         ComponentName xmlConfig = new ComponentName("xml", "config");
8018         ComponentName deviceConfig = new ComponentName("device", "config");
8019         setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
8020         when(mResources
8021                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
8022                 .thenReturn(xmlConfig.flattenToString());
8023         when(mContext.getResources()).thenReturn(mResources);
8024         // Only xmlConfig is valid, deviceConfig is not.
8025         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
8026                 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
8027         when(mAssistants.getDefaultComponents())
8028                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
8029         mService.setNotificationAssistantAccessGrantedCallback(
8030                 mNotificationAssistantAccessGrantedCallback);
8031 
8032         mService.setDefaultAssistantForUser(0);
8033 
8034         verify(mNotificationAssistantAccessGrantedCallback)
8035                 .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false));
8036     }
8037 
8038     @Test
clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne()8039     public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
8040         ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
8041                 generateResetComponentValues();
8042         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
8043         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
8044         ComponentName deviceConfig1 = new ComponentName("device", "config1");
8045         ComponentName deviceConfig2 = new ComponentName("device", "config2");
8046         changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
8047         changes.put(false, new ArrayList());
8048         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
8049         mService.getBinderService().clearData("device", 0, false);
8050         verify(mAssistants, times(1))
8051                 .setPackageOrComponentEnabled(
8052                         eq("device/config2"),
8053                         eq(0), eq(true), eq(false));
8054         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
8055                 eq("device"), eq(0), eq(false), eq(true));
8056     }
8057 
8058     @Test
testNASSettingUpgrade_userSetNull()8059     public void testNASSettingUpgrade_userSetNull() throws RemoteException {
8060         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component1");
8061         TestableNotificationManagerService service = spy(mService);
8062         int userId = 11;
8063         setUsers(new int[]{userId});
8064         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
8065         setNASMigrationDone(false, userId);
8066         when(mAssistants.getDefaultFromConfig())
8067                 .thenReturn(newDefaultComponent);
8068         when(mAssistants.getAllowedComponents(anyInt()))
8069                 .thenReturn(new ArrayList<>());
8070         when(mAssistants.hasUserSet(userId)).thenReturn(true);
8071 
8072         service.migrateDefaultNAS();
8073         assertTrue(service.isNASMigrationDone(userId));
8074         verify(mAssistants, times(1)).clearDefaults();
8075     }
8076 
8077     @Test
testNASSettingUpgrade_userSet()8078     public void testNASSettingUpgrade_userSet() throws RemoteException {
8079         ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component1");
8080         TestableNotificationManagerService service = spy(mService);
8081         int userId = 11;
8082         setUsers(new int[]{userId});
8083         when(mUm.getProfileIds(userId, false)).thenReturn(new int[]{userId});
8084         setNASMigrationDone(false, userId);
8085         when(mAssistants.getDefaultFromConfig())
8086                 .thenReturn(defaultComponent);
8087         when(mAssistants.getAllowedComponents(anyInt()))
8088                 .thenReturn(new ArrayList(Arrays.asList(defaultComponent)));
8089         when(mAssistants.hasUserSet(userId)).thenReturn(true);
8090 
8091         service.migrateDefaultNAS();
8092         verify(mAssistants, times(1)).setUserSet(userId, false);
8093         //resetDefaultAssistantsIfNecessary should invoke from readPolicyXml() and migration
8094         verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
8095     }
8096 
8097     @Test
testNASSettingUpgrade_multiUser()8098     public void testNASSettingUpgrade_multiUser() throws RemoteException {
8099         ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1");
8100         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2");
8101         TestableNotificationManagerService service = spy(mService);
8102         int userId1 = 11;
8103         int userId2 = 12;
8104         setUsers(new int[]{userId1, userId2});
8105         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1});
8106         when(mUm.getProfileIds(userId2, false)).thenReturn(new int[]{userId2});
8107 
8108         setNASMigrationDone(false, userId1);
8109         setNASMigrationDone(false, userId2);
8110         when(mAssistants.getDefaultComponents())
8111                 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
8112         when(mAssistants.getDefaultFromConfig())
8113                 .thenReturn(newDefaultComponent);
8114         //User1: set different NAS
8115         when(mAssistants.getAllowedComponents(userId1))
8116                 .thenReturn(Arrays.asList(oldDefaultComponent));
8117         //User2: set to none
8118         when(mAssistants.getAllowedComponents(userId2))
8119                 .thenReturn(new ArrayList<>());
8120 
8121         when(mAssistants.hasUserSet(userId1)).thenReturn(true);
8122         when(mAssistants.hasUserSet(userId2)).thenReturn(true);
8123 
8124         service.migrateDefaultNAS();
8125         // user1's setting get reset
8126         verify(mAssistants, times(1)).setUserSet(userId1, false);
8127         verify(mAssistants, times(0)).setUserSet(eq(userId2), anyBoolean());
8128         assertTrue(service.isNASMigrationDone(userId2));
8129 
8130     }
8131 
8132     @Test
testNASSettingUpgrade_multiProfile()8133     public void testNASSettingUpgrade_multiProfile() throws RemoteException {
8134         ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1");
8135         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2");
8136         TestableNotificationManagerService service = spy(mService);
8137         int userId1 = 11;
8138         int userId2 = 12; //work profile
8139         setUsers(new int[]{userId1, userId2});
8140         when(mUm.isManagedProfile(userId2)).thenReturn(true);
8141         when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2});
8142 
8143         setNASMigrationDone(false, userId1);
8144         setNASMigrationDone(false, userId2);
8145         when(mAssistants.getDefaultComponents())
8146                 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
8147         when(mAssistants.getDefaultFromConfig())
8148                 .thenReturn(newDefaultComponent);
8149         //Both profiles: set different NAS
8150         when(mAssistants.getAllowedComponents(userId1))
8151                 .thenReturn(Arrays.asList(oldDefaultComponent));
8152         when(mAssistants.getAllowedComponents(userId2))
8153                 .thenReturn(Arrays.asList(oldDefaultComponent));
8154 
8155         when(mAssistants.hasUserSet(userId1)).thenReturn(true);
8156         when(mAssistants.hasUserSet(userId2)).thenReturn(true);
8157 
8158         service.migrateDefaultNAS();
8159         assertFalse(service.isNASMigrationDone(userId1));
8160         assertFalse(service.isNASMigrationDone(userId2));
8161     }
8162 
8163 
8164 
8165     @Test
testNASSettingUpgrade_clearDataAfterMigrationIsDone()8166     public void testNASSettingUpgrade_clearDataAfterMigrationIsDone() throws RemoteException {
8167         ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component");
8168         TestableNotificationManagerService service = spy(mService);
8169         int userId = 12;
8170         setUsers(new int[]{userId});
8171         when(mAssistants.getDefaultComponents())
8172                 .thenReturn(new ArraySet<>(Arrays.asList(defaultComponent)));
8173         when(mAssistants.hasUserSet(userId)).thenReturn(true);
8174         setNASMigrationDone(true, userId);
8175 
8176         //Test User clear data
8177         ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
8178                 generateResetComponentValues();
8179         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
8180         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
8181         changes.put(true, new ArrayList(Arrays.asList(defaultComponent)));
8182         changes.put(false, new ArrayList());
8183         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
8184 
8185         //Clear data
8186         service.getBinderService().clearData("package", userId, false);
8187         //Test migrate flow again
8188         service.migrateDefaultNAS();
8189 
8190         //Migration should not happen again
8191         verify(mAssistants, times(0)).setUserSet(userId, false);
8192         verify(mAssistants, times(0)).clearDefaults();
8193         //resetDefaultAssistantsIfNecessary should only invoke once from readPolicyXml()
8194         verify(mAssistants, times(1)).resetDefaultAssistantsIfNecessary();
8195 
8196     }
8197 
setNASMigrationDone(boolean done, int userId)8198     private void setNASMigrationDone(boolean done, int userId) {
8199         Settings.Secure.putIntForUser(mContext.getContentResolver(),
8200                 Settings.Secure.NAS_SETTINGS_UPDATED, done ? 1 : 0, userId);
8201     }
8202 
setUsers(int[] userIds)8203     private void setUsers(int[] userIds) {
8204         List<UserInfo> users = new ArrayList<>();
8205         for (int id: userIds) {
8206             users.add(new UserInfo(id, String.valueOf(id), 0));
8207         }
8208         for (UserInfo user : users) {
8209             when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
8210         }
8211         when(mUm.getUsers()).thenReturn(users);
8212     }
8213 
8214     @Test
clearDefaultListenersPackageShouldEnableIt()8215     public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
8216         ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
8217                 generateResetComponentValues();
8218         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
8219         ComponentName deviceConfig = new ComponentName("device", "config");
8220         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
8221         changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
8222         changes.put(false, new ArrayList());
8223         when(mListeners.resetComponents(anyString(), anyInt()))
8224             .thenReturn(changes);
8225         mService.getBinderService().clearData("device", 0, false);
8226         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
8227                 eq("device"), eq(0), eq(false), eq(true));
8228     }
8229 
8230     @Test
clearDefaultDnDPackageShouldEnableIt()8231     public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
8232         ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
8233         when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
8234         when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
8235         mService.getBinderService().clearData("pkgName", 0, false);
8236         verify(mConditionProviders, times(1)).resetPackage(
8237                         eq("pkgName"), eq(0));
8238     }
8239 
8240     @Test
testFlagBubble()8241     public void testFlagBubble() throws RemoteException {
8242         setUpPrefsForBubbles(PKG, mUid,
8243                 true /* global */,
8244                 BUBBLE_PREFERENCE_ALL /* app */,
8245                 true /* channel */);
8246 
8247         NotificationRecord nr =
8248                 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
8249 
8250         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8251                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8252         waitForIdle();
8253 
8254         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8255         assertEquals(1, notifs.length);
8256         assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
8257         assertTrue(mService.getNotificationRecord(
8258                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8259     }
8260 
8261     @Test
testFlagBubble_noFlag_appNotAllowed()8262     public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
8263         setUpPrefsForBubbles(PKG, mUid,
8264                 true /* global */,
8265                 BUBBLE_PREFERENCE_NONE /* app */,
8266                 true /* channel */);
8267 
8268         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8269                         "testFlagBubble_noFlag_appNotAllowed");
8270 
8271         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8272                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8273         waitForIdle();
8274 
8275         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8276         assertEquals(1, notifs.length);
8277         assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
8278         assertFalse(mService.getNotificationRecord(
8279                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8280     }
8281 
8282     @Test
testFlagBubbleNotifs_noFlag_whenAppForeground()8283     public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
8284         setUpPrefsForBubbles(PKG, mUid,
8285                 true /* global */,
8286                 BUBBLE_PREFERENCE_ALL /* app */,
8287                 true /* channel */);
8288 
8289         // Notif with bubble metadata but not our other misc requirements
8290         Notification.Builder nb = new Notification.Builder(mContext,
8291                 mTestNotificationChannel.getId())
8292                 .setContentTitle("foo")
8293                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
8294                 .setBubbleMetadata(getBubbleMetadata());
8295         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
8296                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8297         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
8298 
8299         // Say we're foreground
8300         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
8301                 IMPORTANCE_FOREGROUND);
8302         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8303                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8304         waitForIdle();
8305 
8306         // if notif isn't configured properly it doesn't get to bubble just because app is
8307         // foreground.
8308         assertFalse(mService.getNotificationRecord(
8309                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8310     }
8311 
8312     @Test
testFlagBubbleNotifs_flag_messaging()8313     public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
8314         setUpPrefsForBubbles(PKG, mUid,
8315                 true /* global */,
8316                 BUBBLE_PREFERENCE_ALL /* app */,
8317                 true /* channel */);
8318 
8319         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8320                 "testFlagBubbleNotifs_flag_messaging");
8321 
8322         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8323                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8324         waitForIdle();
8325 
8326         // yes allowed, yes messaging, yes bubble
8327         assertTrue(mService.getNotificationRecord(
8328                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8329     }
8330 
8331     @Test
testFlagBubbleNotifs_noFlag_noShortcut()8332     public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException {
8333         setUpPrefsForBubbles(PKG, mUid,
8334                 true /* global */,
8335                 BUBBLE_PREFERENCE_ALL /* app */,
8336                 true /* channel */);
8337 
8338         Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false);
8339         nb.setShortcutId(null);
8340         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
8341                 null, mUid, 0,
8342                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8343 
8344         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
8345                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
8346         waitForIdle();
8347 
8348         // no shortcut no bubble
8349         assertFalse(mService.getNotificationRecord(
8350                 sbn.getKey()).getNotification().isBubbleNotification());
8351     }
8352 
8353     @Test
testFlagBubbleNotifs_noFlag_messaging_appNotAllowed()8354     public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
8355         setUpPrefsForBubbles(PKG, mUid,
8356                 true /* global */,
8357                 BUBBLE_PREFERENCE_NONE /* app */,
8358                 true /* channel */);
8359 
8360         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8361                 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
8362 
8363         // Post the notification
8364         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8365                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8366         waitForIdle();
8367 
8368         // not allowed, no bubble
8369         assertFalse(mService.getNotificationRecord(
8370                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8371     }
8372 
8373     @Test
testFlagBubbleNotifs_noFlag_notBubble()8374     public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
8375         setUpPrefsForBubbles(PKG, mUid,
8376                 true /* global */,
8377                 BUBBLE_PREFERENCE_ALL /* app */,
8378                 true /* channel */);
8379 
8380         // Messaging notif WITHOUT bubble metadata
8381         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
8382                 null /* groupKey */, false /* isSummary */);
8383 
8384         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
8385                 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
8386                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
8387         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
8388 
8389         // Post the notification
8390         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8391                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8392         waitForIdle();
8393 
8394         // no bubble metadata, no bubble
8395         assertFalse(mService.getNotificationRecord(
8396                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8397     }
8398 
8399     @Test
testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed()8400     public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
8401         setUpPrefsForBubbles(PKG, mUid,
8402                 true /* global */,
8403                 BUBBLE_PREFERENCE_ALL /* app */,
8404                 false /* channel */);
8405 
8406         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8407                 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
8408         nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
8409 
8410         // Post the notification
8411         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8412                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8413         waitForIdle();
8414 
8415         // channel not allowed, no bubble
8416         assertFalse(mService.getNotificationRecord(
8417                 nr.getSbn().getKey()).getNotification().isBubbleNotification());
8418     }
8419 
8420     @Test
testCancelNotificationsFromApp_cancelsBubbles()8421     public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
8422         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
8423         nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
8424 
8425         // Post the notification
8426         mBinderService.enqueueNotificationWithTag(PKG, PKG,
8427                 "testAppCancelNotifications_cancelsBubbles",
8428                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
8429                 nrBubble.getSbn().getUserId());
8430         waitForIdle();
8431 
8432         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8433         assertEquals(1, notifs.length);
8434         assertEquals(1, mService.getNotificationRecordCount());
8435 
8436         mBinderService.cancelNotificationWithTag(PKG, PKG,
8437                 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
8438                 nrBubble.getSbn().getUserId());
8439         waitForIdle();
8440 
8441         StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
8442         assertEquals(0, notifs2.length);
8443         assertEquals(0, mService.getNotificationRecordCount());
8444     }
8445 
8446     @Test
testCancelAllNotificationsFromApp_cancelsBubble()8447     public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
8448         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8449         nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
8450         mService.addNotification(nr);
8451 
8452         mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
8453         waitForIdle();
8454 
8455         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8456         assertEquals(0, notifs.length);
8457         assertEquals(0, mService.getNotificationRecordCount());
8458     }
8459 
8460     @Test
testCancelAllNotificationsFromListener_ignoresBubbles()8461     public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
8462         final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
8463         final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
8464         nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
8465 
8466         mService.addNotification(nrNormal);
8467         mService.addNotification(nrBubble);
8468 
8469         mService.getBinderService().cancelNotificationsFromListener(null, null);
8470         waitForIdle();
8471 
8472         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8473         assertEquals(1, notifs.length);
8474         assertEquals(1, mService.getNotificationRecordCount());
8475     }
8476 
8477     @Test
testCancelNotificationsFromListener_cancelsNonBubble()8478     public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception {
8479         // Add non-bubble notif
8480         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8481         mService.addNotification(nr);
8482 
8483         // Cancel via listener
8484         String[] keys = {nr.getSbn().getKey()};
8485         mService.getBinderService().cancelNotificationsFromListener(null, keys);
8486         waitForIdle();
8487 
8488         // Notif not active anymore
8489         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8490         assertEquals(0, notifs.length);
8491         assertEquals(0, mService.getNotificationRecordCount());
8492         // Cancel event is logged
8493         assertEquals(1, mNotificationRecordLogger.numCalls());
8494         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
8495             .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
8496     }
8497 
8498     @Test
testCancelNotificationsFromListener_suppressesBubble()8499     public void testCancelNotificationsFromListener_suppressesBubble() throws Exception {
8500         // Add bubble notif
8501         setUpPrefsForBubbles(PKG, mUid,
8502             true /* global */,
8503             BUBBLE_PREFERENCE_ALL /* app */,
8504             true /* channel */);
8505         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
8506 
8507         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8508             nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8509         waitForIdle();
8510 
8511         // Cancel via listener
8512         String[] keys = {nr.getSbn().getKey()};
8513         mService.getBinderService().cancelNotificationsFromListener(null, keys);
8514         waitForIdle();
8515 
8516         // Bubble notif active and suppressed
8517         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8518         assertEquals(1, notifs.length);
8519         assertEquals(1, mService.getNotificationRecordCount());
8520         assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed());
8521     }
8522 
8523     @Test
testCancelAllNotificationsFromStatusBar_ignoresBubble()8524     public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
8525         // GIVEN a notification bubble
8526         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8527         nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
8528         mService.addNotification(nr);
8529 
8530         // WHEN the status bar clears all notifications
8531         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
8532                 nr.getSbn().getUserId());
8533         waitForIdle();
8534 
8535         // THEN the bubble notification does not get removed
8536         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
8537         assertEquals(1, notifs.length);
8538         assertEquals(1, mService.getNotificationRecordCount());
8539     }
8540 
8541 
8542     @Test
testGetAllowedAssistantAdjustments()8543     public void testGetAllowedAssistantAdjustments() throws Exception {
8544         List<String> adjustments = mBinderService.getAllowedAssistantAdjustments(null);
8545         assertNotNull(adjustments);
8546     }
8547 
8548     @Test
testAdjustRestrictedKey()8549     public void testAdjustRestrictedKey() throws Exception {
8550         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
8551         mService.addNotification(r);
8552         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
8553 
8554         when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
8555         when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
8556 
8557         Bundle signals = new Bundle();
8558         signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
8559         signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
8560         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
8561                "", r.getUser().getIdentifier());
8562 
8563         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
8564         r.applyAdjustments();
8565 
8566         assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
8567         assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
8568     }
8569 
8570     @Test
testAutomaticZenRuleValidation_policyFilterAgreement()8571     public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
8572         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8573                 .thenReturn(true);
8574         mService.setZenHelper(mock(ZenModeHelper.class));
8575         ComponentName owner = new ComponentName(mContext, this.getClass());
8576         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8577         boolean isEnabled = true;
8578         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8579                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
8580 
8581         try {
8582             mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
8583             fail("Zen policy only applies to priority only mode");
8584         } catch (IllegalArgumentException e) {
8585             // yay
8586         }
8587 
8588         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8589                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8590         mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
8591 
8592         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8593                 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
8594         mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
8595     }
8596 
8597     @Test
testAddAutomaticZenRule_systemCallTakesPackageFromOwner()8598     public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception {
8599         mService.isSystemUid = true;
8600         ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
8601         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8602                 .thenReturn(true);
8603         mService.setZenHelper(mockZenModeHelper);
8604         ComponentName owner = new ComponentName("android", "ProviderName");
8605         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8606         boolean isEnabled = true;
8607         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8608                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8609         mBinderService.addAutomaticZenRule(rule, "com.android.settings");
8610 
8611         // verify that zen mode helper gets passed in a package name of "android"
8612         verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(),
8613                 anyInt(), eq(true)); // system call counts as "is system or system ui"
8614     }
8615 
8616     @Test
testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner()8617     public void testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner() throws Exception {
8618         // The multi-user case: where the calling uid doesn't match the system uid, but the calling
8619         // *appid* is the system.
8620         mService.isSystemUid = false;
8621         mService.isSystemAppId = true;
8622         ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
8623         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8624                 .thenReturn(true);
8625         mService.setZenHelper(mockZenModeHelper);
8626         ComponentName owner = new ComponentName("android", "ProviderName");
8627         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8628         boolean isEnabled = true;
8629         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8630                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8631         mBinderService.addAutomaticZenRule(rule, "com.android.settings");
8632 
8633         // verify that zen mode helper gets passed in a package name of "android"
8634         verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(),
8635                 anyInt(),  eq(true));  // system call counts as "system or system ui"
8636     }
8637 
8638     @Test
testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg()8639     public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception {
8640         mService.isSystemUid = false;
8641         mService.isSystemAppId = false;
8642         ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
8643         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
8644                 .thenReturn(true);
8645         mService.setZenHelper(mockZenModeHelper);
8646         ComponentName owner = new ComponentName("android", "ProviderName");
8647         ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
8648         boolean isEnabled = true;
8649         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
8650                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
8651         mBinderService.addAutomaticZenRule(rule, "another.package");
8652 
8653         // verify that zen mode helper gets passed in the package name from the arg, not the owner
8654         verify(mockZenModeHelper).addAutomaticZenRule(
8655                 eq("another.package"), eq(rule), anyString(), anyInt(),
8656                 eq(false));  // doesn't count as a system/systemui call
8657     }
8658 
8659     @Test
onZenModeChanged_sendsBroadcasts()8660     public void onZenModeChanged_sendsBroadcasts() throws Exception {
8661         when(mAmi.getCurrentUserId()).thenReturn(100);
8662         when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102});
8663         when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() {
8664             @Override
8665             public List<String> answer(InvocationOnMock invocation) {
8666                 int userId = invocation.getArgument(0);
8667                 switch (userId) {
8668                     case 100:
8669                         return Lists.newArrayList("a", "b", "c");
8670                     case 101:
8671                         return Lists.newArrayList();
8672                     case 102:
8673                         return Lists.newArrayList("b");
8674                     default:
8675                         throw new IllegalArgumentException(
8676                                 "Why would you ask for packages of userId " + userId + "?");
8677                 }
8678             }
8679         });
8680 
8681         mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
8682                 "testing!");
8683         waitForIdle();
8684 
8685         InOrder inOrder = inOrder(mContext);
8686         // Verify broadcasts for registered receivers
8687         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
8688                 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
8689                         Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null));
8690         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
8691                 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
8692                         Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null));
8693         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
8694                 new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
8695                         Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null));
8696 
8697         // Verify broadcast for packages that manage DND.
8698         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8699                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags(
8700                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
8701         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8702                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
8703                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
8704         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8705                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags(
8706                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
8707         inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
8708                 ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
8709                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
8710     }
8711 
eqIntent(Intent wanted)8712     private static Intent eqIntent(Intent wanted) {
8713         return ArgumentMatchers.argThat(
8714                 new ArgumentMatcher<Intent>() {
8715                     @Override
8716                     public boolean matches(Intent argument) {
8717                         return wanted.filterEquals(argument)
8718                                 && wanted.getFlags() == argument.getFlags();
8719                     }
8720 
8721                     @Override
8722                     public String toString() {
8723                         return wanted.toString();
8724                     }
8725                 });
8726     }
8727 
8728     @Test
8729     public void testAreNotificationsEnabledForPackage() throws Exception {
8730         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
8731                 mUid);
8732 
8733         verify(mPermissionHelper).hasPermission(mUid);
8734     }
8735 
8736     @Test
8737     public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
8738         try {
8739             mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
8740                     mUid + UserHandle.PER_USER_RANGE);
8741             fail("Cannot call cross user without permission");
8742         } catch (SecurityException e) {
8743             // pass
8744         }
8745         verify(mPermissionHelper, never()).hasPermission(anyInt());
8746 
8747         // cross user, with permission, no problem
8748         enableInteractAcrossUsers();
8749         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
8750                 mUid + UserHandle.PER_USER_RANGE);
8751 
8752         verify(mPermissionHelper).hasPermission(mUid + UserHandle.PER_USER_RANGE);
8753     }
8754 
8755     @Test
8756     public void testAreNotificationsEnabledForPackage_viaInternalService() {
8757         mInternalService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid);
8758         verify(mPermissionHelper).hasPermission(mUid);
8759     }
8760 
8761     @Test
8762     public void testGetPackageImportance() throws Exception {
8763         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
8764         assertThat(mBinderService.getPackageImportance(mContext.getPackageName()))
8765                 .isEqualTo(IMPORTANCE_DEFAULT);
8766 
8767         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
8768         assertThat(mBinderService.getPackageImportance(mContext.getPackageName()))
8769                 .isEqualTo(IMPORTANCE_NONE);
8770     }
8771 
8772     @Test
8773     public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
8774         try {
8775             mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
8776                     mUid + UserHandle.PER_USER_RANGE);
8777             fail("Cannot call cross user without permission");
8778         } catch (SecurityException e) {
8779             // pass
8780         }
8781 
8782         // cross user, with permission, no problem
8783         enableInteractAcrossUsers();
8784         mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
8785                 mUid + UserHandle.PER_USER_RANGE);
8786     }
8787 
8788     private void enableInteractAcrossUsers() {
8789         TestablePermissions perms = mContext.getTestablePermissions();
8790         perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
8791     }
8792 
8793     @Test
8794     public void testNotificationBubbleChanged_false() throws Exception {
8795         setUpPrefsForBubbles(PKG, mUid,
8796                 true /* global */,
8797                 BUBBLE_PREFERENCE_ALL /* app */,
8798                 true /* channel */);
8799 
8800         // Notif with bubble metadata
8801         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8802                 "testNotificationBubbleChanged_false");
8803 
8804         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8805                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8806         waitForIdle();
8807 
8808         // Reset as this is called when the notif is first sent
8809         reset(mListeners);
8810 
8811         // First we were a bubble
8812         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
8813         assertEquals(1, notifsBefore.length);
8814         assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
8815 
8816         // Notify we're not a bubble
8817         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
8818         waitForIdle();
8819 
8820         // Make sure we are not a bubble
8821         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
8822         assertEquals(1, notifsAfter.length);
8823         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
8824     }
8825 
8826     @Test
8827     public void testNotificationBubbleChanged_true() throws Exception {
8828         setUpPrefsForBubbles(PKG, mUid,
8829                 true /* global */,
8830                 BUBBLE_PREFERENCE_ALL /* app */,
8831                 true /* channel */);
8832 
8833         // Notif that is not a bubble
8834         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
8835                 1, null, false);
8836         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8837                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8838         waitForIdle();
8839 
8840         // Would be a normal notification because wouldn't have met requirements to bubble
8841         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
8842         assertEquals(1, notifsBefore.length);
8843         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
8844 
8845         // Update the notification to be message style / meet bubble requirements
8846         NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8847                 nr.getSbn().getTag());
8848         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
8849                 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
8850         waitForIdle();
8851 
8852         // Reset as this is called when the notif is first sent
8853         reset(mListeners);
8854 
8855         // Notify we are now a bubble
8856         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
8857         waitForIdle();
8858 
8859         // Make sure we are a bubble
8860         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
8861         assertEquals(1, notifsAfter.length);
8862         assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
8863     }
8864 
8865     @Test
8866     public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
8867         setUpPrefsForBubbles(PKG, mUid,
8868                 true /* global */,
8869                 BUBBLE_PREFERENCE_ALL /* app */,
8870                 true /* channel */);
8871 
8872         // Notif that is not a bubble
8873         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
8874         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8875                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8876         waitForIdle();
8877 
8878         // Reset as this is called when the notif is first sent
8879         reset(mListeners);
8880 
8881         // Would be a normal notification because wouldn't have met requirements to bubble
8882         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
8883         assertEquals(1, notifsBefore.length);
8884         assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
8885 
8886         // Notify we are now a bubble
8887         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
8888         waitForIdle();
8889 
8890         // We still wouldn't be a bubble because the notification didn't meet requirements
8891         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
8892         assertEquals(1, notifsAfter.length);
8893         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
8894     }
8895 
8896     @Test
8897     public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
8898         setUpPrefsForBubbles(PKG, mUid,
8899                 true /* global */,
8900                 BUBBLE_PREFERENCE_ALL /* app */,
8901                 true /* channel */);
8902 
8903         // Notif with bubble metadata
8904         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8905                 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
8906 
8907         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8908                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8909         waitForIdle();
8910         // Flag shouldn't be modified
8911         NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
8912         assertFalse(recordToCheck.isFlagBubbleRemoved());
8913 
8914         // Notify we're not a bubble
8915         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
8916         waitForIdle();
8917         // Flag should be modified
8918         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
8919         assertTrue(recordToCheck.isFlagBubbleRemoved());
8920 
8921 
8922         // Update the notif
8923         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8924                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8925         waitForIdle();
8926         // And the flag is reset
8927         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
8928         assertFalse(recordToCheck.isFlagBubbleRemoved());
8929     }
8930 
8931     @Test
8932     public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
8933         setUpPrefsForBubbles(PKG, mUid,
8934                 true /* global */,
8935                 BUBBLE_PREFERENCE_ALL /* app */,
8936                 true /* channel */);
8937 
8938         // Notif with bubble metadata
8939         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
8940                 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
8941 
8942         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8943                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8944         waitForIdle();
8945         // Flag shouldn't be modified
8946         NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
8947         assertFalse(recordToCheck.isFlagBubbleRemoved());
8948 
8949         // Notify we're not a bubble
8950         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
8951         waitForIdle();
8952         // Flag should be modified
8953         recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
8954         assertTrue(recordToCheck.isFlagBubbleRemoved());
8955 
8956         // Notify we are a bubble
8957         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
8958         waitForIdle();
8959         // And the flag is reset
8960         assertFalse(recordToCheck.isFlagBubbleRemoved());
8961     }
8962 
8963     @Test
8964     public void testOnBubbleMetadataFlagChanged() throws Exception {
8965         setUpPrefsForBubbles(PKG, mUid,
8966                 true /* global */,
8967                 BUBBLE_PREFERENCE_ALL /* app */,
8968                 true /* channel */);
8969 
8970         // Post a bubble notification
8971         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
8972         // Set this so that the bubble can be suppressed
8973         nr.getNotification().getBubbleMetadata().setFlags(
8974                 Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE);
8975         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
8976                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
8977         waitForIdle();
8978 
8979         // Check the flags
8980         Notification n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
8981         assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
8982         assertFalse(n.getBubbleMetadata().getAutoExpandBubble());
8983         assertFalse(n.getBubbleMetadata().isBubbleSuppressed());
8984         assertTrue(n.getBubbleMetadata().isBubbleSuppressable());
8985 
8986         // Reset as this is called when the notif is first sent
8987         reset(mListeners);
8988 
8989         // Test: change the flags
8990         int flags = Notification.BubbleMetadata.FLAG_SUPPRESSABLE_BUBBLE;
8991         flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE;
8992         flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
8993         flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE;
8994         mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), flags);
8995         waitForIdle();
8996 
8997         // Check
8998         n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
8999         assertEquals(flags, n.getBubbleMetadata().getFlags());
9000 
9001         // Reset to check again
9002         reset(mListeners);
9003 
9004         // Test: clear flags
9005         mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(), 0);
9006         waitForIdle();
9007 
9008         // Check
9009         n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
9010         assertEquals(0, n.getBubbleMetadata().getFlags());
9011     }
9012 
9013     @Test
9014     public void testOnBubbleMetadataChangedToSuppressNotification_soundStopped()
9015             throws RemoteException {
9016         IRingtonePlayer mockPlayer = mock(IRingtonePlayer.class);
9017         when(mAudioManager.getRingtonePlayer()).thenReturn(mockPlayer);
9018         // Set up volume to be above 0 for the sound to actually play
9019         when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
9020 
9021         setUpPrefsForBubbles(PKG, mUid,
9022                 true /* global */,
9023                 BUBBLE_PREFERENCE_ALL /* app */,
9024                 true /* channel */);
9025 
9026         // Post a bubble notification
9027         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
9028         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9029                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9030         waitForIdle();
9031 
9032         // Test: suppress notification via bubble metadata update
9033         mService.mNotificationDelegate.onBubbleMetadataFlagChanged(nr.getKey(),
9034                 Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
9035         waitForIdle();
9036 
9037         // Check audio is stopped
9038         verify(mockPlayer).stopAsync();
9039     }
9040 
9041     @Test
9042     public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
9043         int userId = UserManager.isHeadlessSystemUserMode()
9044                 ? UserHandle.getUserId(UID_HEADLESS)
9045                 : USER_SYSTEM;
9046 
9047         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId);
9048         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
9049                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9050         waitForIdle();
9051 
9052         // A notification exists for the given record
9053         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9054         assertEquals(1, notifsBefore.length);
9055 
9056         reset(mPackageManager);
9057 
9058         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9059 
9060         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9061                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9062                 nr.getSbn().getUid());
9063 
9064         // Grant permission called for the UID of SystemUI under the target user ID
9065         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9066                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
9067                 anyInt(), eq(nr.getSbn().getUserId()));
9068     }
9069 
9070     @Test
9071     public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
9072         int userId = UserManager.isHeadlessSystemUserMode()
9073                 ? UserHandle.getUserId(UID_HEADLESS)
9074                 : USER_SYSTEM;
9075 
9076         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId);
9077         waitForIdle();
9078 
9079         // No notifications exist for the given record
9080         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9081         assertEquals(0, notifsBefore.length);
9082 
9083         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9084 
9085         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9086                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9087                 nr.getSbn().getUid());
9088 
9089         // Grant permission still called if no NotificationRecord exists for the given key
9090         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9091                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
9092                 anyInt(), eq(nr.getSbn().getUserId()));
9093     }
9094 
9095     @Test
9096     public void testGrantInlineReplyUriPermission_userAll() throws Exception {
9097         // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
9098         NotificationRecord nr =
9099                 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
9100         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
9101                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9102         waitForIdle();
9103 
9104         // A notification exists for the given record
9105         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
9106         assertEquals(1, notifsBefore.length);
9107 
9108         reset(mPackageManager);
9109 
9110         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9111 
9112         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9113                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9114                 nr.getSbn().getUid());
9115 
9116         // Target user for the grant is USER_ALL instead of USER_SYSTEM
9117         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9118                 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
9119                 anyInt(), UserManager.isHeadlessSystemUserMode()
9120                         ? eq(UserHandle.getUserId(UID_HEADLESS))
9121                         : eq(USER_SYSTEM));
9122     }
9123 
9124     @Test
9125     public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
9126         // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
9127         int otherUserId = 11;
9128         NotificationRecord nr =
9129                 generateNotificationRecord(mTestNotificationChannel, otherUserId);
9130         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
9131                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9132         waitForIdle();
9133 
9134         // A notification exists for the given record
9135         List<StatusBarNotification> notifsBefore =
9136                 mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList();
9137         assertEquals(1, notifsBefore.size());
9138 
9139         reset(mPackageManager);
9140 
9141         Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9142 
9143         int uid = 0; // sysui on primary user
9144         int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
9145         String sysuiPackage = "sysui";
9146         final String[] sysuiPackages = new String[] { sysuiPackage };
9147         when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
9148 
9149         // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
9150         // time this is called
9151         when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
9152                 .thenReturn(otherUserUid);
9153 
9154         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9155                 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
9156 
9157         // Target user for the grant is USER_ALL instead of USER_SYSTEM
9158         verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
9159                 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
9160                 eq(otherUserId));
9161     }
9162 
9163     @Test
9164     public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
9165         int userId = UserManager.isHeadlessSystemUserMode()
9166                 ? UserHandle.getUserId(UID_HEADLESS)
9167                 : USER_SYSTEM;
9168 
9169         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, userId);
9170         reset(mPackageManager);
9171 
9172         Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9173         Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
9174 
9175         // create an inline record with two uris in it
9176         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9177                 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9178                 nr.getSbn().getUid());
9179         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9180                 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9181                 nr.getSbn().getUid());
9182 
9183         InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
9184         assertNotNull(record); // record exists
9185         assertEquals(record.getUris().size(), 2); // record has two uris in it
9186 
9187         mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
9188                 nr.getSbn().getUid());
9189 
9190         // permissionOwner destroyed
9191         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
9192                 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
9193     }
9194 
9195 
9196     @Test
9197     public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
9198         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
9199         reset(mPackageManager);
9200 
9201         mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
9202                 nr.getSbn().getUid());
9203 
9204         // no permissionOwner destroyed
9205         verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
9206                 any(), eq(null), eq(~0), eq(nr.getUserId()));
9207     }
9208 
9209     @Test
9210     public void testClearInlineReplyUriPermission_userAll() throws Exception {
9211         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
9212                 UserHandle.USER_ALL);
9213         reset(mPackageManager);
9214 
9215         Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
9216 
9217         // create an inline record a uri in it
9218         mService.mNotificationDelegate.grantInlineReplyUriPermission(
9219                 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
9220                 nr.getSbn().getUid());
9221 
9222         InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
9223         assertNotNull(record); // record exists
9224 
9225         mService.mNotificationDelegate.clearInlineReplyUriPermissions(
9226                 nr.getKey(), nr.getSbn().getUid());
9227 
9228         // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
9229         verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
9230                 eq(record.getPermissionOwner()), eq(null), eq(~0),
9231                 UserManager.isHeadlessSystemUserMode()
9232                         ? eq(UserHandle.getUserId(UID_HEADLESS))
9233                         : eq(USER_SYSTEM));
9234     }
9235 
9236     @Test
9237     public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
9238         setUpPrefsForBubbles(PKG, mUid,
9239                 true /* global */,
9240                 BUBBLE_PREFERENCE_ALL /* app */,
9241                 true /* channel */);
9242 
9243         // And we are low ram
9244         when(mActivityManager.isLowRamDevice()).thenReturn(true);
9245 
9246         // Notification that would typically bubble
9247         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9248                 "testNotificationBubbles_disabled_lowRamDevice");
9249         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9250                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9251         waitForIdle();
9252 
9253         // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
9254         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9255         assertEquals(1, notifsAfter.length);
9256         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
9257     }
9258 
9259     @Test
9260     public void testRemoveLargeRemoteViews() throws Exception {
9261         int removeSize = mContext.getResources().getInteger(
9262                 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
9263 
9264         RemoteViews rv = mock(RemoteViews.class);
9265         when(rv.estimateMemoryUsage()).thenReturn(removeSize);
9266         when(rv.clone()).thenReturn(rv);
9267         RemoteViews rv1 = mock(RemoteViews.class);
9268         when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
9269         when(rv1.clone()).thenReturn(rv1);
9270         RemoteViews rv2 = mock(RemoteViews.class);
9271         when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
9272         when(rv2.clone()).thenReturn(rv2);
9273         RemoteViews rv3 = mock(RemoteViews.class);
9274         when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
9275         when(rv3.clone()).thenReturn(rv3);
9276         RemoteViews rv4 = mock(RemoteViews.class);
9277         when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
9278         when(rv4.clone()).thenReturn(rv4);
9279         // note: different!
9280         RemoteViews rv5 = mock(RemoteViews.class);
9281         when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
9282         when(rv5.clone()).thenReturn(rv5);
9283 
9284         Notification np = new Notification.Builder(mContext, "test")
9285                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
9286                 .setContentText("test")
9287                 .setCustomContentView(rv)
9288                 .setCustomBigContentView(rv1)
9289                 .setCustomHeadsUpContentView(rv2)
9290                 .build();
9291         Notification n = new Notification.Builder(mContext, "test")
9292                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
9293                 .setContentText("test")
9294                 .setCustomContentView(rv3)
9295                 .setCustomBigContentView(rv4)
9296                 .setCustomHeadsUpContentView(rv5)
9297                 .setPublicVersion(np)
9298                 .build();
9299 
9300         assertNotNull(np.contentView);
9301         assertNotNull(np.bigContentView);
9302         assertNotNull(np.headsUpContentView);
9303 
9304         assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
9305         assertNotNull(n.publicVersion.contentView);
9306         assertNotNull(n.publicVersion.bigContentView);
9307         assertNotNull(n.publicVersion.headsUpContentView);
9308 
9309         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
9310 
9311         assertNull(n.contentView);
9312         assertNull(n.bigContentView);
9313         assertNotNull(n.headsUpContentView);
9314         assertNull(n.publicVersion.contentView);
9315         assertNull(n.publicVersion.bigContentView);
9316         assertNull(n.publicVersion.headsUpContentView);
9317 
9318         verify(mUsageStats, times(5)).registerImageRemoved(PKG);
9319     }
9320 
9321     @Test
9322     public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
9323             throws Exception {
9324         setUpPrefsForBubbles(PKG, mUid,
9325                 true /* global */,
9326                 BUBBLE_PREFERENCE_ALL /* app */,
9327                 true /* channel */);
9328 
9329         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9330                 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
9331         // Modify metadata flags
9332         nr.getSbn().getNotification().getBubbleMetadata().setFlags(
9333                 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
9334                         | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
9335 
9336         // Ensure we're not foreground
9337         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
9338                 IMPORTANCE_VISIBLE);
9339 
9340         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9341                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9342         waitForIdle();
9343 
9344         // yes allowed, yes messaging, yes bubble
9345         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9346         assertTrue(notif.isBubbleNotification());
9347 
9348         // The flag should have failed since we're not foreground
9349         assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
9350     }
9351 
9352     @Test
9353     public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
9354             throws RemoteException {
9355         setUpPrefsForBubbles(PKG, mUid,
9356                 true /* global */,
9357                 BUBBLE_PREFERENCE_ALL /* app */,
9358                 true /* channel */);
9359 
9360         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9361                 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
9362         // Modify metadata flags
9363         nr.getSbn().getNotification().getBubbleMetadata().setFlags(
9364                 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
9365                         | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
9366 
9367         // Ensure we are in the foreground
9368         when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
9369                 IMPORTANCE_FOREGROUND);
9370 
9371         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9372                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9373         waitForIdle();
9374 
9375         // yes allowed, yes messaging, yes bubble
9376         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9377         assertTrue(notif.isBubbleNotification());
9378 
9379         // Our flags should have passed since we are foreground
9380         assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
9381         assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
9382     }
9383 
9384     @Test
9385     public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
9386             throws RemoteException {
9387         setUpPrefsForBubbles(PKG, mUid,
9388                 true /* global */,
9389                 BUBBLE_PREFERENCE_ALL /* app */,
9390                 true /* channel */);
9391 
9392         ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
9393                 ArgumentCaptor.forClass(LauncherApps.Callback.class);
9394 
9395         // Messaging notification with shortcut info
9396         Notification.BubbleMetadata metadata =
9397                 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build();
9398         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9399                 null /* groupKey */, false /* isSummary */);
9400         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
9401         nb.setBubbleMetadata(metadata);
9402         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
9403                 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
9404         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9405 
9406         // Test: Send the bubble notification
9407         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9408                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9409         waitForIdle();
9410 
9411         // Verify:
9412 
9413         // Make sure we register the callback for shortcut changes
9414         verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
9415 
9416         // yes allowed, yes messaging w/shortcut, yes bubble
9417         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9418         assertTrue(notif.isBubbleNotification());
9419 
9420         // Make sure the shortcut is cached.
9421         verify(mShortcutServiceInternal).cacheShortcuts(
9422                 anyInt(), any(), eq(PKG), eq(singletonList(VALID_CONVO_SHORTCUT_ID)),
9423                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
9424 
9425         // Test: Remove the shortcut
9426         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
9427         launcherAppsCallback.getValue().onShortcutsChanged(PKG, emptyList(),
9428                 UserHandle.getUserHandleForUid(mUid));
9429         waitForIdle();
9430 
9431         // Verify:
9432 
9433         // Make sure callback is unregistered
9434         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
9435 
9436         // We're no longer a bubble
9437         NotificationRecord notif2 = mService.getNotificationRecord(
9438                 nr.getSbn().getKey());
9439         assertNull(notif2.getShortcutInfo());
9440         assertFalse(notif2.getNotification().isBubbleNotification());
9441     }
9442 
9443     @Test
9444     public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
9445             throws RemoteException {
9446         final String shortcutId = "someshortcutId";
9447         setUpPrefsForBubbles(PKG, mUid,
9448                 true /* global */,
9449                 BUBBLE_PREFERENCE_ALL /* app */,
9450                 true /* channel */);
9451 
9452         ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
9453                 ArgumentCaptor.forClass(LauncherApps.Callback.class);
9454 
9455         // Messaging notification with shortcut info
9456         Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
9457                 shortcutId).build();
9458         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9459                 null /* groupKey */, false /* isSummary */);
9460         nb.setShortcutId(shortcutId);
9461         nb.setBubbleMetadata(metadata);
9462         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
9463                 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
9464         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9465 
9466         // Pretend the shortcut exists
9467         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
9468         ShortcutInfo info = mock(ShortcutInfo.class);
9469         when(info.getPackage()).thenReturn(PKG);
9470         when(info.getId()).thenReturn(shortcutId);
9471         when(info.getUserId()).thenReturn(USER_SYSTEM);
9472         when(info.isLongLived()).thenReturn(true);
9473         when(info.isEnabled()).thenReturn(true);
9474         shortcutInfos.add(info);
9475         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
9476         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
9477                 anyString(), anyInt(), any())).thenReturn(true);
9478 
9479         // Test: Send the bubble notification
9480         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9481                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9482         waitForIdle();
9483 
9484         // Verify:
9485 
9486         // Make sure we register the callback for shortcut changes
9487         verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
9488 
9489         // yes allowed, yes messaging w/shortcut, yes bubble
9490         Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
9491         assertTrue(notif.isBubbleNotification());
9492 
9493         // Make sure the shortcut is cached.
9494         verify(mShortcutServiceInternal).cacheShortcuts(
9495                 anyInt(), any(), eq(PKG), eq(singletonList(shortcutId)),
9496                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
9497 
9498         // Test: Remove the notification
9499         mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9500                 nr.getSbn().getId(), nr.getSbn().getUserId());
9501         waitForIdle();
9502 
9503         // Verify:
9504 
9505         // Make sure callback is unregistered
9506         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
9507     }
9508 
9509     @Test
9510     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
9511             throws Exception {
9512         setUpPrefsForBubbles(PKG, mUid,
9513                 true /* global */,
9514                 BUBBLE_PREFERENCE_ALL /* app */,
9515                 true /* channel */);
9516 
9517         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
9518                 true /* summaryAutoCancel */);
9519 
9520         // Dismiss summary
9521         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
9522                 true);
9523         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
9524                 nrSummary.getUserId(), nrSummary.getKey(),
9525                 NotificationStats.DISMISSAL_SHADE,
9526                 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
9527         waitForIdle();
9528 
9529         // The bubble should still exist
9530         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9531         assertEquals(1, notifsAfter.length);
9532     }
9533 
9534     @Test
9535     public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
9536             throws Exception {
9537         setUpPrefsForBubbles(PKG, mUid,
9538                 true /* global */,
9539                 BUBBLE_PREFERENCE_ALL /* app */,
9540                 true /* channel */);
9541 
9542         NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
9543                 true /* summaryAutoCancel */);
9544 
9545         // Click summary
9546         final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
9547                 true);
9548         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
9549                 nrSummary.getKey(), nv);
9550         waitForIdle();
9551 
9552         // The bubble should still exist
9553         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9554         assertEquals(1, notifsAfter.length);
9555 
9556         // Check we got the click log and associated dismissal logs
9557         assertEquals(6, mNotificationRecordLogger.numCalls());
9558         // Skip the notification-creation logs
9559         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
9560                 mNotificationRecordLogger.event(3));
9561         assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
9562                 mNotificationRecordLogger.event(4));
9563         assertEquals(NotificationRecordLogger.NotificationCancelledEvent
9564                         .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
9565                 mNotificationRecordLogger.event(5));
9566     }
9567 
9568     @Test
9569     public void testNotificationBubbles_bubbleStays_whenClicked()
9570             throws Exception {
9571         setUpPrefsForBubbles(PKG, mUid,
9572                 true /* global */,
9573                 BUBBLE_PREFERENCE_ALL /* app */,
9574                 true /* channel */);
9575 
9576         // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
9577         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
9578         nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
9579         mService.addNotification(nr);
9580 
9581         // WHEN we click the notification
9582         final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
9583         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
9584                 nr.getKey(), nv);
9585         waitForIdle();
9586 
9587         // THEN the bubble should still exist
9588         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9589         assertEquals(1, notifsAfter.length);
9590 
9591         // Check we got the click log
9592         assertEquals(1, mNotificationRecordLogger.numCalls());
9593         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
9594                 mNotificationRecordLogger.event(0));
9595     }
9596 
9597     /**
9598      * When something is bubble'd and the bubble is dismissed, but the notification is still
9599      * visible, clicking on the notification shouldn't auto-cancel it because clicking on
9600      * it will produce a bubble.
9601      */
9602     @Test
9603     public void testNotificationBubbles_bubbleStays_whenClicked_afterBubbleDismissed()
9604             throws Exception {
9605         setUpPrefsForBubbles(PKG, mUid,
9606                 true /* global */,
9607                 BUBBLE_PREFERENCE_ALL /* app */,
9608                 true /* channel */);
9609 
9610         // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
9611         final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
9612         nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
9613         nr.setAllowBubble(true);
9614         mService.addNotification(nr);
9615 
9616         // And the bubble is dismissed
9617         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(),
9618                 false /* isBubble */, 0 /* bubbleFlags */);
9619         waitForIdle();
9620         assertTrue(nr.isFlagBubbleRemoved());
9621 
9622         // WHEN we click the notification
9623         final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
9624         mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
9625                 nr.getKey(), nv);
9626         waitForIdle();
9627 
9628         // THEN the bubble should still exist
9629         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
9630         assertEquals(1, notifsAfter.length);
9631 
9632         // Check we got the click log
9633         assertEquals(1, mNotificationRecordLogger.numCalls());
9634         assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
9635                 mNotificationRecordLogger.event(0));
9636     }
9637 
9638     @Test
9639     public void testLoadDefaultApprovedServices_emptyResources() {
9640         TestableResources tr = mContext.getOrCreateTestableResources();
9641         tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
9642         tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
9643         tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
9644         setDefaultAssistantInDeviceConfig("");
9645 
9646         mService.loadDefaultApprovedServices(USER_SYSTEM);
9647 
9648         verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
9649         verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
9650         verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
9651     }
9652 
9653     @Test
9654     public void testLoadDefaultApprovedServices_dnd() {
9655         TestableResources tr = mContext.getOrCreateTestableResources();
9656         tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
9657         when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
9658                 .thenReturn(new ArraySet<>());
9659 
9660         mService.loadDefaultApprovedServices(USER_SYSTEM);
9661 
9662         verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
9663     }
9664 
9665     // TODO: add tests for the rest of the non-empty cases
9666 
9667     @Test
9668     public void testOnUnlockUser() {
9669         UserInfo ui = new UserInfo();
9670         ui.id = 10;
9671         mService.onUserUnlocked(new TargetUser(ui));
9672         waitForIdle();
9673 
9674         verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
9675     }
9676 
9677     @Test
9678     public void testOnStopUser() {
9679         UserInfo ui = new UserInfo();
9680         ui.id = 10;
9681         mService.onUserStopping(new TargetUser(ui));
9682         waitForIdle();
9683 
9684         verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
9685     }
9686 
9687     @Test
9688     public void testHandleOnPackageChanged() {
9689         String[] pkgs = new String[] {PKG, PKG_N_MR1};
9690         int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
9691 
9692         mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
9693 
9694         verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
9695 
9696         mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
9697 
9698         verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
9699         verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
9700     }
9701 
9702     @Test
9703     public void testNotificationHistory_addNoisyNotification() throws Exception {
9704         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
9705                 null /* tvExtender */);
9706         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9707                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9708         waitForIdle();
9709 
9710         verify(mHistoryManager, times(1)).addNotification(any());
9711     }
9712 
9713     @Test
9714     public void createConversationNotificationChannel() throws Exception {
9715         int userId = UserManager.isHeadlessSystemUserMode()
9716                 ? UserHandle.getUserId(UID_HEADLESS)
9717                 : USER_SYSTEM;
9718 
9719         NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
9720         original.setAllowBubbles(!original.canBubble());
9721         original.setShowBadge(!original.canShowBadge());
9722 
9723         Parcel parcel = Parcel.obtain();
9724         original.writeToParcel(parcel, 0);
9725         parcel.setDataPosition(0);
9726         NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
9727         assertEquals(original, orig);
9728         assertFalse(TextUtils.isEmpty(orig.getName()));
9729 
9730         mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
9731                 orig)));
9732 
9733         mBinderService.createConversationNotificationChannelForPackage(
9734                 PKG, mUid, orig, "friend");
9735 
9736         NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
9737                 PKG, userId, PKG, original.getId(), false, "friend");
9738 
9739         assertEquals(original.getName(), friendChannel.getName());
9740         assertEquals(original.getId(), friendChannel.getParentChannelId());
9741         assertEquals("friend", friendChannel.getConversationId());
9742         assertEquals(null, original.getConversationId());
9743         assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
9744         assertFalse(friendChannel.canBubble()); // can't be modified by app
9745         assertFalse(original.getId().equals(friendChannel.getId()));
9746         assertNotNull(friendChannel.getId());
9747     }
9748 
9749     @Test
9750     public void testCorrectCategory_systemOn_appCannotTurnOff() {
9751         int requested = 0;
9752         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9753 
9754         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9755                 system);
9756 
9757         assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
9758     }
9759 
9760     @Test
9761     public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
9762         int requested = PRIORITY_CATEGORY_CALLS;
9763         int system = PRIORITY_CATEGORY_CALLS;
9764 
9765         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9766                 system);
9767 
9768         assertEquals(PRIORITY_CATEGORY_CALLS, actual);
9769     }
9770 
9771     @Test
9772     public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
9773         int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9774         int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9775 
9776         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9777                 system);
9778 
9779         assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
9780     }
9781 
9782     @Test
9783     public void testCorrectCategory_systemOff_appCannotTurnOn() {
9784         int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
9785         int system = PRIORITY_CATEGORY_CALLS;
9786 
9787         int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
9788                 system);
9789 
9790         assertEquals(PRIORITY_CATEGORY_CALLS, actual);
9791     }
9792 
9793     @Test
9794     public void testGetConversationsForPackage_hasShortcut() throws Exception {
9795         mService.setPreferencesHelper(mPreferencesHelper);
9796         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
9797         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
9798         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
9799         channel1.setConversationId("parent1", "convo 1");
9800         convo1.setNotificationChannel(channel1);
9801         convos.add(convo1);
9802 
9803         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
9804         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
9805         channel2.setConversationId("parent1", "convo 2");
9806         convo2.setNotificationChannel(channel2);
9807         convos.add(convo2);
9808         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
9809 
9810         ShortcutInfo si = mock(ShortcutInfo.class);
9811         when(si.getPackage()).thenReturn(PKG_P);
9812         when(si.getId()).thenReturn("convo");
9813         when(si.getUserId()).thenReturn(USER_SYSTEM);
9814         when(si.getLabel()).thenReturn("Hello");
9815         when(si.isLongLived()).thenReturn(true);
9816         when(si.isEnabled()).thenReturn(true);
9817         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
9818         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
9819                 anyString(), anyInt(), any())).thenReturn(true);
9820 
9821         List<ConversationChannelWrapper> conversations =
9822                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9823         assertEquals(si, conversations.get(0).getShortcutInfo());
9824         assertEquals(si, conversations.get(1).getShortcutInfo());
9825 
9826         // Returns null shortcuts when locked.
9827         when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false);
9828         conversations =
9829                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9830         assertThat(conversations.get(0).getShortcutInfo()).isNull();
9831         assertThat(conversations.get(1).getShortcutInfo()).isNull();
9832     }
9833 
9834     @Test
9835     public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
9836         mService.setPreferencesHelper(mPreferencesHelper);
9837         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
9838         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
9839         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
9840         channel1.setConversationId("parent1", "convo 1");
9841         convo1.setNotificationChannel(channel1);
9842         convos.add(convo1);
9843 
9844         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
9845         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
9846         channel2.setConversationId("parent1", "convo 2");
9847         convo2.setNotificationChannel(channel2);
9848         convos.add(convo2);
9849         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
9850 
9851         ShortcutInfo si = mock(ShortcutInfo.class);
9852         when(si.getPackage()).thenReturn(PKG_P);
9853         when(si.getId()).thenReturn("convo");
9854         when(si.getUserId()).thenReturn(USER_SYSTEM);
9855         when(si.getLabel()).thenReturn("Hello");
9856         when(si.isLongLived()).thenReturn(false);
9857         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
9858 
9859         List<ConversationChannelWrapper> conversations =
9860                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9861         assertNull(conversations.get(0).getShortcutInfo());
9862         assertNull(conversations.get(1).getShortcutInfo());
9863     }
9864 
9865     @Test
9866     public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
9867         mService.setPreferencesHelper(mPreferencesHelper);
9868         ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
9869         ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
9870         NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
9871         channel1.setConversationId("parent1", "convo 1");
9872         convo1.setNotificationChannel(channel1);
9873         convos.add(convo1);
9874 
9875         ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
9876         NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
9877         channel2.setConversationId("parent1", "convo 2");
9878         convo2.setNotificationChannel(channel2);
9879         convos.add(convo2);
9880         when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
9881         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
9882 
9883         List<ConversationChannelWrapper> conversations =
9884                 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
9885         assertNull(conversations.get(0).getShortcutInfo());
9886         assertNull(conversations.get(1).getShortcutInfo());
9887     }
9888 
9889     @Test
9890     public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
9891         mService.setShortcutHelper(null);
9892         NotificationRecord nr =
9893                 generateMessageBubbleNotifRecord(mTestNotificationChannel,
9894                         "testShortcutHelperNull_doesntCrashEnqueue");
9895         try {
9896             mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9897                     nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9898             waitForIdle();
9899         } catch (Exception e) {
9900             fail(e.getMessage());
9901         }
9902     }
9903 
9904     @Test
9905     public void testRecordMessages_invalidMsg() throws RemoteException {
9906         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9907                 null /* groupKey */, false /* isSummary */);
9908         nb.setShortcutId(null);
9909         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
9910                 "testRecordMessages_invalidMsg", mUid, 0, nb.build(),
9911                 UserHandle.getUserHandleForUid(mUid), null, 0);
9912         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9913 
9914         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
9915         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
9916                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9917         waitForIdle();
9918 
9919         assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
9920     }
9921 
9922     @Test
9923     public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException {
9924         Notification.Builder nb = new Notification.Builder(mContext,
9925                 mTestNotificationChannel.getId())
9926                 .setContentTitle("foo")
9927                 .setShortcutId(null)
9928                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
9929                 .setCategory(Notification.CATEGORY_MESSAGE);
9930         StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1,
9931                 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(),
9932                 UserHandle.getUserHandleForUid(mUid), null, 0);
9933         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9934 
9935         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
9936         mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(),
9937                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9938         waitForIdle();
9939 
9940         // PKG_O is allowed to be in conversation space b/c of override in
9941         // TestableNotificationManagerService
9942         assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid));
9943     }
9944 
9945     @Test
9946     public void testRecordMessages_validMsg() throws RemoteException {
9947         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9948                 null /* groupKey */, false /* isSummary */);
9949         nb.setShortcutId(null);
9950         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
9951                 "testRecordMessages_validMsg", mUid, 0, nb.build(),
9952                 UserHandle.getUserHandleForUid(mUid), null, 0);
9953         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9954 
9955         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
9956                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9957         waitForIdle();
9958 
9959         assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
9960 
9961         nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9962                 "testRecordMessages_validMsg");
9963 
9964         mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
9965                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9966         waitForIdle();
9967 
9968         assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid));
9969     }
9970 
9971     @Test
9972     public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException {
9973         NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
9974                 "testRecordMessages_invalidMsg_afterValidMsg_1");
9975         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9976                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9977         waitForIdle();
9978         assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation());
9979 
9980         mBinderService.cancelAllNotifications(PKG, mUid);
9981         waitForIdle();
9982 
9983         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
9984                 null /* groupKey */, false /* isSummary */);
9985         nb.setShortcutId(null);
9986         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
9987                 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
9988                 UserHandle.getUserHandleForUid(mUid), null, 0);
9989          nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
9990 
9991         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
9992                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
9993         waitForIdle();
9994 
9995         assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation());
9996     }
9997 
9998     @Test
9999     public void testCanPostFgsWhenOverLimit() throws RemoteException {
10000         when(mAmi.applyForegroundServiceNotification(
10001                 any(), anyString(), anyInt(), anyString(), anyInt()))
10002                 .thenReturn(SHOW_IMMEDIATELY);
10003         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
10004             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
10005                     i, null, false).getSbn();
10006             mBinderService.enqueueNotificationWithTag(PKG, PKG,
10007                     "testCanPostFgsWhenOverLimit",
10008                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
10009         }
10010 
10011         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
10012         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
10013         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10014                 "testCanPostFgsWhenOverLimit - fgs over limit!",
10015                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
10016 
10017         waitForIdle();
10018 
10019         StatusBarNotification[] notifs =
10020                 mBinderService.getActiveNotifications(sbn.getPackageName());
10021         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
10022         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
10023                 mService.getNotificationRecordCount());
10024     }
10025 
10026     @Test
10027     public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
10028         when(mAmi.applyForegroundServiceNotification(
10029                 any(), anyString(), anyInt(), anyString(), anyInt()))
10030                 .thenReturn(SHOW_IMMEDIATELY);
10031         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
10032             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
10033                     i, null, false).getSbn();
10034             mBinderService.enqueueNotificationWithTag(PKG, PKG,
10035                     "testCanPostFgsWhenOverLimit",
10036                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
10037             waitForIdle();
10038         }
10039 
10040         final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
10041                 100, null, false).getSbn();
10042         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
10043         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10044                 "testCanPostFgsWhenOverLimit - fgs over limit!",
10045                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
10046 
10047         final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
10048                 101, null, false).getSbn();
10049         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10050                 "testCanPostFgsWhenOverLimit - non fgs over limit!",
10051                 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
10052 
10053 
10054         when(mAmi.applyForegroundServiceNotification(
10055                 any(), anyString(), anyInt(), anyString(), anyInt()))
10056                 .thenReturn(NOT_FOREGROUND_SERVICE);
10057         final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel,
10058                 101, null, false).getSbn();
10059         sbn3.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
10060         mBinderService.enqueueNotificationWithTag(PKG, PKG,
10061                 "testCanPostFgsWhenOverLimit - fake fgs over limit!",
10062                 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId());
10063 
10064         waitForIdle();
10065 
10066         StatusBarNotification[] notifs =
10067                 mBinderService.getActiveNotifications(sbn.getPackageName());
10068         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
10069         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
10070                 mService.getNotificationRecordCount());
10071     }
10072 
10073     @Test
10074     public void testIsVisibleToListener_notEnabled() {
10075         StatusBarNotification sbn = mock(StatusBarNotification.class);
10076         when(sbn.getUserId()).thenReturn(10);
10077         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10078         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10079         info.userid = 10;
10080         when(info.isSameUser(anyInt())).thenReturn(true);
10081         when(assistant.isSameUser(anyInt())).thenReturn(true);
10082         when(info.enabledAndUserMatches(info.userid)).thenReturn(false);
10083         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10084 
10085         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10086     }
10087 
10088     @Test
10089     public void testIsVisibleToListener_noAssistant() {
10090         StatusBarNotification sbn = mock(StatusBarNotification.class);
10091         when(sbn.getUserId()).thenReturn(10);
10092         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10093         info.userid = 10;
10094         when(info.isSameUser(anyInt())).thenReturn(true);
10095         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10096         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(null);
10097 
10098         assertTrue(mService.isVisibleToListener(sbn, 0, info));
10099     }
10100 
10101     @Test
10102     public void testIsVisibleToListener_assistant_differentUser() {
10103         StatusBarNotification sbn = mock(StatusBarNotification.class);
10104         when(sbn.getUserId()).thenReturn(10);
10105         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10106         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10107         info.userid = 0;
10108         when(info.isSameUser(anyInt())).thenReturn(true);
10109         when(assistant.isSameUser(anyInt())).thenReturn(true);
10110         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10111         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10112 
10113         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10114     }
10115 
10116     @Test
10117     public void testIsVisibleToListener_assistant_sameUser() {
10118         StatusBarNotification sbn = mock(StatusBarNotification.class);
10119         when(sbn.getUserId()).thenReturn(10);
10120         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10121         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10122         info.userid = 10;
10123         when(info.isSameUser(anyInt())).thenReturn(true);
10124         when(assistant.isSameUser(anyInt())).thenReturn(true);
10125         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10126         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10127 
10128         assertTrue(mService.isVisibleToListener(sbn, 0, info));
10129     }
10130 
10131     @Test
10132     public void testIsVisibleToListener_mismatchedType() {
10133         when(mNlf.isTypeAllowed(anyInt())).thenReturn(false);
10134 
10135         StatusBarNotification sbn = mock(StatusBarNotification.class);
10136         when(sbn.getUserId()).thenReturn(10);
10137         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10138         ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
10139         info.userid = 10;
10140         when(info.isSameUser(anyInt())).thenReturn(true);
10141         when(assistant.isSameUser(anyInt())).thenReturn(true);
10142         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10143         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10144 
10145         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10146     }
10147 
10148     @Test
10149     public void testIsVisibleToListener_disallowedPackage() {
10150         when(mNlf.isPackageAllowed(any())).thenReturn(false);
10151 
10152         StatusBarNotification sbn = mock(StatusBarNotification.class);
10153         when(sbn.getUserId()).thenReturn(10);
10154         ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
10155         ManagedServices.ManagedServiceInfo assistant =
10156                 mock(ManagedServices.ManagedServiceInfo.class);
10157         info.userid = 10;
10158         when(info.isSameUser(anyInt())).thenReturn(true);
10159         when(assistant.isSameUser(anyInt())).thenReturn(true);
10160         when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
10161         when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
10162 
10163         assertFalse(mService.isVisibleToListener(sbn, 0, info));
10164     }
10165 
10166     @Test
10167     public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedFirst() {
10168         final NotificationRecord parent = spy(generateNotificationRecord(
10169                 mTestNotificationChannel, 1, "group", true));
10170         final NotificationRecord child = spy(generateNotificationRecord(
10171                 mTestNotificationChannel, 2, "group", false));
10172         mService.addNotification(parent);
10173         mService.addNotification(child);
10174 
10175         InOrder inOrder = inOrder(parent, child);
10176 
10177         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
10178                 parent.getUserId());
10179         waitForIdle();
10180         inOrder.verify(parent).recordDismissalSentiment(anyInt());
10181         inOrder.verify(child).recordDismissalSentiment(anyInt());
10182     }
10183 
10184     @Test
10185     public void testUserInitiatedCancelAll_groupCancellationOrder_groupPostedSecond() {
10186         final NotificationRecord parent = spy(generateNotificationRecord(
10187                 mTestNotificationChannel, 1, "group", true));
10188         final NotificationRecord child = spy(generateNotificationRecord(
10189                 mTestNotificationChannel, 2, "group", false));
10190         mService.addNotification(child);
10191         mService.addNotification(parent);
10192 
10193         InOrder inOrder = inOrder(parent, child);
10194 
10195         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
10196                 parent.getUserId());
10197         waitForIdle();
10198         inOrder.verify(parent).recordDismissalSentiment(anyInt());
10199         inOrder.verify(child).recordDismissalSentiment(anyInt());
10200     }
10201 
10202     @Test
10203     public void testImmutableBubbleIntent() throws Exception {
10204         when(mAmi.getPendingIntentFlags(pi1))
10205                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10206         NotificationRecord r = generateMessageBubbleNotifRecord(true,
10207                 mTestNotificationChannel, 7, "testImmutableBubbleIntent", null, false);
10208         try {
10209             mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10210                     r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10211 
10212             waitForIdle();
10213             fail("Allowed a bubble with an immutable intent to be posted");
10214         } catch (IllegalArgumentException e) {
10215             // good
10216         }
10217     }
10218 
10219     @Test
10220     public void testMutableBubbleIntent() throws Exception {
10221         when(mAmi.getPendingIntentFlags(pi1))
10222                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10223         NotificationRecord r = generateMessageBubbleNotifRecord(true,
10224                 mTestNotificationChannel, 7, "testMutableBubbleIntent", null, false);
10225 
10226         mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10227                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10228 
10229         waitForIdle();
10230         StatusBarNotification[] notifs =
10231                 mBinderService.getActiveNotifications(r.getSbn().getPackageName());
10232         assertEquals(1, notifs.length);
10233     }
10234 
10235     @Test
10236     public void testImmutableDirectReplyActionIntent() throws Exception {
10237         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10238                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10239         NotificationRecord r = generateMessageBubbleNotifRecord(false,
10240                 mTestNotificationChannel, 7, "testImmutableDirectReplyActionIntent", null, false);
10241         try {
10242             mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10243                     r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10244 
10245             waitForIdle();
10246             fail("Allowed a direct reply with an immutable intent to be posted");
10247         } catch (IllegalArgumentException e) {
10248             // good
10249         }
10250     }
10251 
10252     @Test
10253     public void testMutableDirectReplyActionIntent() throws Exception {
10254         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10255                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10256         NotificationRecord r = generateMessageBubbleNotifRecord(false,
10257                 mTestNotificationChannel, 7, "testMutableDirectReplyActionIntent", null, false);
10258         mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10259                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10260 
10261         waitForIdle();
10262         StatusBarNotification[] notifs =
10263                 mBinderService.getActiveNotifications(r.getSbn().getPackageName());
10264         assertEquals(1, notifs.length);
10265     }
10266 
10267     @Test
10268     public void testImmutableDirectReplyContextualActionIntent() throws Exception {
10269         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10270                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10271         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10272 
10273         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10274         ArrayList<Notification.Action> extraAction = new ArrayList<>();
10275         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
10276         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
10277                 PendingIntent.FLAG_IMMUTABLE);
10278         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
10279         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
10280                 inputIntent).addRemoteInput(remoteInput)
10281                 .build();
10282         extraAction.add(replyAction);
10283         Bundle signals = new Bundle();
10284         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
10285         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
10286                 r.getUser());
10287         r.addAdjustment(adjustment);
10288         r.applyAdjustments();
10289 
10290         try {
10291             mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(),
10292                     r.getSbn().getTag(), r, false, false);
10293             fail("Allowed a contextual direct reply with an immutable intent to be posted");
10294         } catch (IllegalArgumentException e) {
10295             // good
10296         }
10297     }
10298 
10299     @Test
10300     public void testMutableDirectReplyContextualActionIntent() throws Exception {
10301         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10302                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10303         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10304         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10305         ArrayList<Notification.Action> extraAction = new ArrayList<>();
10306         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
10307         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
10308                 new Intent().setPackage(mContext.getPackageName()),
10309                 PendingIntent.FLAG_MUTABLE);
10310         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
10311         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
10312                 inputIntent).addRemoteInput(remoteInput)
10313                 .build();
10314         extraAction.add(replyAction);
10315         Bundle signals = new Bundle();
10316         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
10317         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
10318                 r.getUser());
10319         r.addAdjustment(adjustment);
10320         r.applyAdjustments();
10321 
10322         mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(),
10323                 r.getSbn().getTag(), r, false, false);
10324     }
10325 
10326     @Test
10327     public void testImmutableActionIntent() throws Exception {
10328         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10329                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10330         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10331 
10332         mBinderService.enqueueNotificationWithTag(PKG, PKG, r.getSbn().getTag(),
10333                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
10334 
10335         waitForIdle();
10336         StatusBarNotification[] notifs =
10337                 mBinderService.getActiveNotifications(r.getSbn().getPackageName());
10338         assertEquals(1, notifs.length);
10339     }
10340 
10341     @Test
10342     public void testImmutableContextualActionIntent() throws Exception {
10343         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10344                 .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
10345         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10346         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
10347         ArrayList<Notification.Action> extraAction = new ArrayList<>();
10348         extraAction.add(new Notification.Action(0, "hello", null));
10349         Bundle signals = new Bundle();
10350         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
10351         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
10352                 r.getUser());
10353         r.addAdjustment(adjustment);
10354         r.applyAdjustments();
10355 
10356         mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(),
10357                     r.getSbn().getTag(), r, false, false);
10358     }
10359 
10360     @Test
10361     public void testMigrateNotificationFilter_migrationAllAllowed() throws Exception {
10362         int uid = 9000;
10363         int[] userIds = new int[] {mUserId, 1000};
10364         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10365         List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries");
10366         for (int userId : userIds) {
10367             for (String pkg : disallowedApps) {
10368                 when(mPackageManager.getPackageUid(pkg, 0, userId)).thenReturn(uid++);
10369             }
10370         }
10371 
10372         when(mListeners.getNotificationListenerFilter(any())).thenReturn(
10373                 new NotificationListenerFilter());
10374 
10375         mBinderService.migrateNotificationFilter(null,
10376                 FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
10377                 disallowedApps);
10378 
10379         ArgumentCaptor<NotificationListenerFilter> captor =
10380                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10381         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10382 
10383         assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
10384                 captor.getValue().getTypes());
10385         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9000)));
10386         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9002)));
10387         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 9003)));
10388 
10389         // hypothetical other user untouched
10390         assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 10000)));
10391     }
10392 
10393     @Test
10394     public void testMigrateNotificationFilter_noPreexistingFilter() throws Exception {
10395         int[] userIds = new int[] {mUserId};
10396         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10397         List<String> disallowedApps = ImmutableList.of("apples");
10398         when(mPackageManager.getPackageUid("apples", 0, mUserId))
10399                 .thenReturn(1001);
10400 
10401         when(mListeners.getNotificationListenerFilter(any())).thenReturn(null);
10402 
10403         mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING,
10404                 disallowedApps);
10405 
10406         ArgumentCaptor<NotificationListenerFilter> captor =
10407                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10408         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10409 
10410         assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes());
10411         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
10412     }
10413 
10414     @Test
10415     public void testMigrateNotificationFilter_existingTypeFilter() throws Exception {
10416         int[] userIds = new int[] {mUserId};
10417         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10418         List<String> disallowedApps = ImmutableList.of("apples");
10419         when(mPackageManager.getPackageUid("apples", 0, mUserId))
10420                 .thenReturn(1001);
10421 
10422         when(mListeners.getNotificationListenerFilter(any())).thenReturn(
10423                 new NotificationListenerFilter(FLAG_FILTER_TYPE_CONVERSATIONS, new ArraySet<>()));
10424 
10425         mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING,
10426                 disallowedApps);
10427 
10428         ArgumentCaptor<NotificationListenerFilter> captor =
10429                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10430         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10431 
10432         // type isn't saved but pkg list is
10433         assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS, captor.getValue().getTypes());
10434         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
10435     }
10436 
10437     @Test
10438     public void testMigrateNotificationFilter_existingPkgFilter() throws Exception {
10439         int[] userIds = new int[] {mUserId};
10440         when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
10441         List<String> disallowedApps = ImmutableList.of("apples");
10442         when(mPackageManager.getPackageUid("apples", 0, mUserId))
10443                 .thenReturn(1001);
10444 
10445         NotificationListenerFilter preexisting = new NotificationListenerFilter();
10446         preexisting.addPackage(new VersionedPackage("test", 1002));
10447         when(mListeners.getNotificationListenerFilter(any())).thenReturn(preexisting);
10448 
10449         mBinderService.migrateNotificationFilter(null, FLAG_FILTER_TYPE_ONGOING,
10450                 disallowedApps);
10451 
10452         ArgumentCaptor<NotificationListenerFilter> captor =
10453                 ArgumentCaptor.forClass(NotificationListenerFilter.class);
10454         verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
10455 
10456         // type is saved but pkg list isn't
10457         assertEquals(FLAG_FILTER_TYPE_ONGOING, captor.getValue().getTypes());
10458         assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
10459         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002)));
10460     }
10461 
10462     @Test
10463     public void testGetNotificationChannelsBypassingDnd_blocked() throws RemoteException {
10464         mService.setPreferencesHelper(mPreferencesHelper);
10465 
10466         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10467 
10468         assertThat(mBinderService.getNotificationChannelsBypassingDnd(PKG, mUid).getList())
10469                 .isEmpty();
10470         verify(mPreferencesHelper, never()).getNotificationChannelsBypassingDnd(PKG, mUid);
10471     }
10472 
10473     @Test
10474     public void testMatchesCallFilter_noPermissionShouldThrow() throws Exception {
10475         // set the testable NMS to not system uid/appid
10476         mService.isSystemUid = false;
10477         mService.isSystemAppId = false;
10478 
10479         // make sure a caller without listener access or read_contacts permission can't call
10480         // matchesCallFilter.
10481         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false);
10482         doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
10483                 eq("android.permission.READ_CONTACTS"), anyString());
10484 
10485         try {
10486             // shouldn't matter what we're passing in, if we get past this line fail immediately
10487             ((INotificationManager) mService.mService).matchesCallFilter(null);
10488             fail("call to matchesCallFilter with no permissions should fail");
10489         } catch (SecurityException e) {
10490             // pass
10491         }
10492     }
10493 
10494     @Test
10495     public void testMatchesCallFilter_hasSystemPermission() throws Exception {
10496         // set the testable NMS to system uid
10497         mService.isSystemUid = true;
10498 
10499         // make sure caller doesn't have listener access or read_contacts permission
10500         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false);
10501         doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
10502                 eq("android.permission.READ_CONTACTS"), anyString());
10503 
10504         try {
10505             ((INotificationManager) mService.mService).matchesCallFilter(null);
10506             // pass, but check that we actually checked for system permissions
10507             assertTrue(mService.countSystemChecks > 0);
10508         } catch (SecurityException e) {
10509             fail("call to matchesCallFilter with just system permissions should work");
10510         }
10511     }
10512 
10513     @Test
10514     public void testMatchesCallFilter_hasListenerPermission() throws Exception {
10515         mService.isSystemUid = false;
10516         mService.isSystemAppId = false;
10517 
10518         // make sure a caller with only listener access and not read_contacts permission can call
10519         // matchesCallFilter.
10520         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(true);
10521         doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
10522                 eq("android.permission.READ_CONTACTS"), anyString());
10523 
10524         try {
10525             ((INotificationManager) mService.mService).matchesCallFilter(null);
10526             // pass, this is not a functionality test
10527         } catch (SecurityException e) {
10528             fail("call to matchesCallFilter with listener permissions should work");
10529         }
10530     }
10531 
10532     @Test
10533     public void testMatchesCallFilter_hasContactsPermission() throws Exception {
10534         mService.isSystemUid = false;
10535         mService.isSystemAppId = false;
10536 
10537         // make sure a caller with only read_contacts permission and not listener access can call
10538         // matchesCallFilter.
10539         when(mListeners.hasAllowedListener(anyString(), anyInt())).thenReturn(false);
10540         doNothing().when(mContext).enforceCallingPermission(
10541                 eq("android.permission.READ_CONTACTS"), anyString());
10542 
10543         try {
10544             ((INotificationManager) mService.mService).matchesCallFilter(null);
10545             // pass, this is not a functionality test
10546         } catch (SecurityException e) {
10547             fail("call to matchesCallFilter with listener permissions should work");
10548         }
10549     }
10550 
10551     @Test
10552     public void testMediaNotificationsBypassBlock() throws Exception {
10553         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10554                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10555         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10556 
10557         Notification.Builder nb = new Notification.Builder(
10558                 mContext, mTestNotificationChannel.getId())
10559                 .setContentTitle("foo")
10560                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10561                 .addAction(new Notification.Action.Builder(null, "test", null).build());
10562         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10563                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10564         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10565 
10566         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10567 
10568         // normal blocked notifications - blocked
10569         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10570                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10571 
10572         // just using the style - blocked
10573         nb.setStyle(new Notification.MediaStyle());
10574         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10575                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10576         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10577 
10578         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10579                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10580 
10581         // using the style, but incorrect type in session - blocked
10582         nb.setStyle(new Notification.MediaStyle());
10583         Bundle extras = new Bundle();
10584         extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent());
10585         nb.addExtras(extras);
10586         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10587                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10588         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10589 
10590         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10591                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10592 
10593         // style + media session - bypasses block
10594         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
10595         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10596                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10597         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10598 
10599         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10600                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
10601     }
10602 
10603     @Test
10604     public void testMediaNotificationsBypassBlock_atPost() throws Exception {
10605         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
10606         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10607 
10608         Notification.Builder nb = new Notification.Builder(
10609                 mContext, mTestNotificationChannel.getId())
10610                 .setContentTitle("foo")
10611                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10612                 .addAction(new Notification.Action.Builder(null, "test", null).build());
10613         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10614                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10615         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10616 
10617         when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false);
10618 
10619         mService.addEnqueuedNotification(r);
10620         NotificationManagerService.PostNotificationRunnable runnable =
10621                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
10622                         r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
10623         runnable.run();
10624         waitForIdle();
10625 
10626         verify(mUsageStats).registerBlocked(any());
10627         verify(mUsageStats, never()).registerPostedByApp(any());
10628 
10629         // just using the style - blocked
10630         mService.clearNotifications();
10631         reset(mUsageStats);
10632         nb.setStyle(new Notification.MediaStyle());
10633         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10634                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10635         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10636 
10637         mService.addEnqueuedNotification(r);
10638         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
10639                 r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
10640         runnable.run();
10641         waitForIdle();
10642 
10643         verify(mUsageStats).registerBlocked(any());
10644         verify(mUsageStats, never()).registerPostedByApp(any());
10645 
10646         // style + media session - bypasses block
10647         mService.clearNotifications();
10648         reset(mUsageStats);
10649         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
10650         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10651                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10652         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10653 
10654         mService.addEnqueuedNotification(r);
10655         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
10656                 r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
10657         runnable.run();
10658         waitForIdle();
10659 
10660         verify(mUsageStats, never()).registerBlocked(any());
10661         verify(mUsageStats).registerPostedByApp(any());
10662     }
10663 
10664     @Test
10665     public void testCallNotificationsBypassBlock() throws Exception {
10666         when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
10667                 .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
10668         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10669 
10670         Notification.Builder nb = new Notification.Builder(
10671                 mContext, mTestNotificationChannel.getId())
10672                 .setContentTitle("foo")
10673                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
10674                 .addAction(new Notification.Action.Builder(null, "test", null).build());
10675         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10676                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10677         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10678 
10679         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10680 
10681         // normal blocked notifications - blocked
10682         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10683                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10684 
10685         // just using the style - blocked
10686         Person person = new Person.Builder()
10687                 .setName("caller")
10688                 .build();
10689         nb.setStyle(Notification.CallStyle.forOngoingCall(
10690                 person, mock(PendingIntent.class)));
10691         nb.setFullScreenIntent(mock(PendingIntent.class), true);
10692         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10693                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10694         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10695 
10696         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10697                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isFalse();
10698 
10699         // style + managed call - bypasses block
10700         when(mTelecomManager.isInManagedCall()).thenReturn(true);
10701         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10702                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
10703 
10704         // style + self managed call - bypasses block
10705         when(mTelecomManager.isInSelfManagedCall(
10706                 r.getSbn().getPackageName(), r.getUser())).thenReturn(true);
10707         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10708                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
10709 
10710         // set telecom manager to null - blocked
10711         mService.setTelecomManager(null);
10712         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10713                            r.getSbn().getId(), r.getSbn().getTag(), r, false, false))
10714                 .isFalse();
10715 
10716         // set telecom feature to false - blocked
10717         when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false);
10718         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10719                            r.getSbn().getId(), r.getSbn().getTag(), r, false, false))
10720                 .isFalse();
10721 
10722         // telecom manager is not ready - blocked
10723         mService.setTelecomManager(mTelecomManager);
10724         when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready"));
10725         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
10726                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false))
10727                 .isFalse();
10728     }
10729 
10730     @Test
10731     public void testCallNotificationsBypassBlock_atPost() throws Exception {
10732         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
10733         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
10734 
10735         Notification.Builder nb =
10736                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
10737                         .setContentTitle("foo")
10738                         .setSmallIcon(android.R.drawable.sym_def_app_icon)
10739                         .addAction(new Notification.Action.Builder(null, "test", null).build());
10740         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
10741                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
10742         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10743 
10744         when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
10745 
10746         // normal blocked notifications - blocked
10747         mService.addEnqueuedNotification(r);
10748         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10749                 mPostNotificationTrackerFactory.newTracker(null)).run();
10750         waitForIdle();
10751 
10752         verify(mUsageStats).registerBlocked(any());
10753         verify(mUsageStats, never()).registerPostedByApp(any());
10754 
10755         // just using the style - blocked
10756         mService.clearNotifications();
10757         reset(mUsageStats);
10758         Person person = new Person.Builder().setName("caller").build();
10759         nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class)));
10760         nb.setFullScreenIntent(mock(PendingIntent.class), true);
10761         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(),
10762                 UserHandle.getUserHandleForUid(mUid), null, 0);
10763         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
10764 
10765         mService.addEnqueuedNotification(r);
10766         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10767                 mPostNotificationTrackerFactory.newTracker(null)).run();
10768         waitForIdle();
10769 
10770         verify(mUsageStats).registerBlocked(any());
10771         verify(mUsageStats, never()).registerPostedByApp(any());
10772 
10773         // style + managed call - bypasses block
10774         mService.clearNotifications();
10775         reset(mUsageStats);
10776         when(mTelecomManager.isInManagedCall()).thenReturn(true);
10777 
10778         mService.addEnqueuedNotification(r);
10779         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10780                 mPostNotificationTrackerFactory.newTracker(null)).run();
10781         waitForIdle();
10782 
10783         verify(mUsageStats, never()).registerBlocked(any());
10784         verify(mUsageStats).registerPostedByApp(any());
10785 
10786         // style + self managed call - bypasses block
10787         mService.clearNotifications();
10788         reset(mUsageStats);
10789         when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser()))
10790                 .thenReturn(true);
10791 
10792         mService.addEnqueuedNotification(r);
10793         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10794                 mPostNotificationTrackerFactory.newTracker(null)).run();
10795         waitForIdle();
10796 
10797         verify(mUsageStats, never()).registerBlocked(any());
10798         verify(mUsageStats).registerPostedByApp(any());
10799 
10800         // set telecom manager to null - notifications should be blocked
10801         // but post notifications runnable should not crash
10802         mService.clearNotifications();
10803         reset(mUsageStats);
10804         mService.setTelecomManager(null);
10805 
10806         mService.addEnqueuedNotification(r);
10807         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10808                 mPostNotificationTrackerFactory.newTracker(null)).run();
10809         waitForIdle();
10810 
10811         verify(mUsageStats).registerBlocked(any());
10812         verify(mUsageStats, never()).registerPostedByApp(any());
10813 
10814         // set FEATURE_TELECOM to false - notifications should be blocked
10815         // but post notifications runnable should not crash
10816         mService.setTelecomManager(mTelecomManager);
10817         when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false);
10818         reset(mUsageStats);
10819         mService.setTelecomManager(null);
10820 
10821         mService.addEnqueuedNotification(r);
10822         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10823                 mPostNotificationTrackerFactory.newTracker(null)).run();
10824         waitForIdle();
10825 
10826         verify(mUsageStats).registerBlocked(any());
10827         verify(mUsageStats, never()).registerPostedByApp(any());
10828 
10829         // telecom is not ready - notifications should be blocked but no crashes
10830         mService.setTelecomManager(mTelecomManager);
10831         when(mTelecomManager.isInCall()).thenThrow(new IllegalStateException("not ready"));
10832         reset(mUsageStats);
10833 
10834         mService.addEnqueuedNotification(r);
10835         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
10836                 mPostNotificationTrackerFactory.newTracker(null)).run();
10837         waitForIdle();
10838 
10839         verify(mUsageStats).registerBlocked(any());
10840         verify(mUsageStats, never()).registerPostedByApp(any());
10841     }
10842 
10843     @Test
10844     public void testGetAllUsersNotificationPermissions() {
10845         // In this case, there are multiple users each with notification permissions (and also,
10846         // for good measure, some without).
10847         // make sure the collection returned contains info for all of them
10848         final List<UserInfo> userInfos = new ArrayList<>();
10849         userInfos.add(new UserInfo(0, "user0", 0));
10850         userInfos.add(new UserInfo(1, "user1", 0));
10851         userInfos.add(new UserInfo(2, "user2", 0));
10852         when(mUm.getUsers()).thenReturn(userInfos);
10853 
10854         // construct the permissions for each of them
10855         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> permissions0 = new ArrayMap<>(),
10856                 permissions1 = new ArrayMap<>();
10857         permissions0.put(new Pair<>(10, "package1"), new Pair<>(true, false));
10858         permissions0.put(new Pair<>(20, "package2"), new Pair<>(false, true));
10859         permissions1.put(new Pair<>(11, "package1"), new Pair<>(false, false));
10860         permissions1.put(new Pair<>(21, "package2"), new Pair<>(true, true));
10861         when(mPermissionHelper.getNotificationPermissionValues(0)).thenReturn(permissions0);
10862         when(mPermissionHelper.getNotificationPermissionValues(1)).thenReturn(permissions1);
10863         when(mPermissionHelper.getNotificationPermissionValues(2)).thenReturn(new ArrayMap<>());
10864 
10865         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> combinedPermissions =
10866                 mService.getAllUsersNotificationPermissions();
10867         assertTrue(combinedPermissions.get(new Pair<>(10, "package1")).first);
10868         assertFalse(combinedPermissions.get(new Pair<>(10, "package1")).second);
10869         assertFalse(combinedPermissions.get(new Pair<>(20, "package2")).first);
10870         assertTrue(combinedPermissions.get(new Pair<>(20, "package2")).second);
10871         assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).first);
10872         assertFalse(combinedPermissions.get(new Pair<>(11, "package1")).second);
10873         assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).first);
10874         assertTrue(combinedPermissions.get(new Pair<>(21, "package2")).second);
10875     }
10876 
10877     @Test
10878     public void testGetActiveNotification_filtersUsers() throws Exception {
10879         when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
10880 
10881         NotificationRecord nr0 =
10882                 generateNotificationRecord(mTestNotificationChannel, 0);
10883         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
10884                 nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId());
10885 
10886         NotificationRecord nr10 =
10887                 generateNotificationRecord(mTestNotificationChannel, 10);
10888         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
10889                 nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId());
10890 
10891         NotificationRecord nr11 =
10892                 generateNotificationRecord(mTestNotificationChannel, 11);
10893         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
10894                 nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId());
10895         waitForIdle();
10896 
10897         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
10898         assertEquals(2, notifs.length);
10899         for (StatusBarNotification sbn : notifs) {
10900             if (sbn.getUserId() == 11) {
10901                 fail("leaked data across users");
10902             }
10903         }
10904     }
10905 
10906     @Test
10907     public void testUngroupingOngoingAutoSummary() throws Exception {
10908         NotificationRecord nr0 =
10909                 generateNotificationRecord(mTestNotificationChannel, 0);
10910         NotificationRecord nr1 =
10911                 generateNotificationRecord(mTestNotificationChannel, 0);
10912         nr1.getSbn().getNotification().flags |= FLAG_ONGOING_EVENT;
10913 
10914         mService.addNotification(nr0);
10915         mService.addNotification(nr1);
10916 
10917         // grouphelper is a mock here, so make the calls it would make
10918 
10919         // add summary
10920         mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(),
10921                 nr1.getSbn().getPackageName(), nr1.getKey(),
10922                 GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT));
10923 
10924         // cancel both children
10925         mBinderService.cancelNotificationWithTag(PKG, PKG, nr0.getSbn().getTag(),
10926                 nr0.getSbn().getId(), nr0.getSbn().getUserId());
10927         mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.getSbn().getTag(),
10928                 nr1.getSbn().getId(), nr1.getSbn().getUserId());
10929         waitForIdle();
10930 
10931         // group helper would send 'remove summary' event
10932         mService.clearAutogroupSummaryLocked(nr1.getUserId(), nr1.getSbn().getPackageName());
10933         waitForIdle();
10934 
10935         // make sure the summary was removed and not re-posted
10936         assertThat(mService.getNotificationRecordCount()).isEqualTo(0);
10937     }
10938 
10939     @Test
10940     public void testUngroupingAutoSummary_differentUsers() throws Exception {
10941         NotificationRecord nr0 =
10942                 generateNotificationRecord(mTestNotificationChannel, 0, USER_SYSTEM);
10943         NotificationRecord nr1 =
10944                 generateNotificationRecord(mTestNotificationChannel, 1, USER_SYSTEM);
10945 
10946         // add notifications + summary for USER_SYSTEM
10947         mService.addNotification(nr0);
10948         mService.addNotification(nr1);
10949         mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(),
10950                 nr1.getSbn().getPackageName(), nr1.getKey(), GroupHelper.BASE_FLAGS));
10951 
10952         // add notifications + summary for USER_ALL
10953         NotificationRecord nr0_all =
10954                 generateNotificationRecord(mTestNotificationChannel, 2, UserHandle.USER_ALL);
10955         NotificationRecord nr1_all =
10956                 generateNotificationRecord(mTestNotificationChannel, 3, UserHandle.USER_ALL);
10957 
10958         mService.addNotification(nr0_all);
10959         mService.addNotification(nr1_all);
10960         mService.addNotification(mService.createAutoGroupSummary(nr0_all.getUserId(),
10961                 nr0_all.getSbn().getPackageName(), nr0_all.getKey(), GroupHelper.BASE_FLAGS));
10962 
10963         // cancel both children for USER_ALL
10964         mBinderService.cancelNotificationWithTag(PKG, PKG, nr0_all.getSbn().getTag(),
10965                 nr0_all.getSbn().getId(), UserHandle.USER_ALL);
10966         mBinderService.cancelNotificationWithTag(PKG, PKG, nr1_all.getSbn().getTag(),
10967                 nr1_all.getSbn().getId(), UserHandle.USER_ALL);
10968         waitForIdle();
10969 
10970         // group helper would send 'remove summary' event
10971         mService.clearAutogroupSummaryLocked(UserHandle.USER_ALL,
10972                 nr0_all.getSbn().getPackageName());
10973         waitForIdle();
10974 
10975         // make sure the right summary was removed
10976         assertThat(mService.getNotificationCount(nr0_all.getSbn().getPackageName(),
10977                 UserHandle.USER_ALL, 0, null)).isEqualTo(0);
10978 
10979         // the USER_SYSTEM notifications + summary were not removed
10980         assertThat(mService.getNotificationCount(nr0.getSbn().getPackageName(),
10981                 USER_SYSTEM, 0, null)).isEqualTo(3);
10982     }
10983 
10984     @Test
10985     public void testStrongAuthTracker_isInLockDownMode() {
10986         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
10987                 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
10988         mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
10989         assertTrue(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
10990         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(mContext.getUserId());
10991         mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
10992         assertFalse(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
10993     }
10994 
10995     @Test
10996     public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() {
10997         // post 2 notifications from 2 packages
10998         NotificationRecord pkgA = new NotificationRecord(mContext,
10999                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
11000         mService.addNotification(pkgA);
11001         NotificationRecord pkgB = new NotificationRecord(mContext,
11002                 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
11003         mService.addNotification(pkgB);
11004 
11005         // when entering the lockdown mode, cancel the 2 notifications.
11006         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
11007                 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
11008         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11009         assertTrue(mStrongAuthTracker.isInLockDownMode(0));
11010 
11011         // the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN.
11012         ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
11013         verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any());
11014         assertEquals(REASON_LOCKDOWN, captor.getValue().intValue());
11015 
11016         // exit lockdown mode.
11017         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
11018         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11019         assertFalse(mStrongAuthTracker.isInLockDownMode(0));
11020 
11021         // the notifyPostedLocked function is called twice.
11022         verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong());
11023         //verify(mListeners, times(2)).notifyPostedLocked(any(), any());
11024     }
11025 
11026     @Test
11027     public void testMakeRankingUpdateLockedInLockDownMode() {
11028         // post 2 notifications from a same package
11029         NotificationRecord pkgA = new NotificationRecord(mContext,
11030                 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
11031         mService.addNotification(pkgA);
11032         NotificationRecord pkgB = new NotificationRecord(mContext,
11033                 generateSbn("a", 1000, 9, 1), mTestNotificationChannel);
11034         mService.addNotification(pkgB);
11035 
11036         mService.setIsVisibleToListenerReturnValue(true);
11037         NotificationRankingUpdate nru = mService.makeRankingUpdateLocked(null);
11038         assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
11039 
11040         // when only user 0 entering the lockdown mode, its notification will be suppressed.
11041         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
11042                 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
11043         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11044         assertTrue(mStrongAuthTracker.isInLockDownMode(0));
11045         assertFalse(mStrongAuthTracker.isInLockDownMode(1));
11046 
11047         nru = mService.makeRankingUpdateLocked(null);
11048         assertEquals(1, nru.getRankingMap().getOrderedKeys().length);
11049 
11050         // User 0 exits lockdown mode. Its notification will be resumed.
11051         mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
11052         mStrongAuthTracker.onStrongAuthRequiredChanged(0);
11053         assertFalse(mStrongAuthTracker.isInLockDownMode(0));
11054         assertFalse(mStrongAuthTracker.isInLockDownMode(1));
11055 
11056         nru = mService.makeRankingUpdateLocked(null);
11057         assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
11058     }
11059 
11060     @Test
11061     public void testMaybeShowReviewPermissionsNotification_flagOff() {
11062         mService.setShowReviewPermissionsNotification(false);
11063         reset(mMockNm);
11064 
11065         // If state is SHOULD_SHOW, it would show, but not if the flag is off!
11066         Settings.Global.putInt(mContext.getContentResolver(),
11067                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11068                 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
11069         mService.maybeShowInitialReviewPermissionsNotification();
11070         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11071     }
11072 
11073     @Test
11074     public void testMaybeShowReviewPermissionsNotification_unknown() {
11075         mService.setShowReviewPermissionsNotification(true);
11076         reset(mMockNm);
11077 
11078         // Set up various possible states of the settings int and confirm whether or not the
11079         // notification is shown as expected
11080 
11081         // Initial state: default/unknown setting, make sure nothing happens
11082         Settings.Global.putInt(mContext.getContentResolver(),
11083                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11084                 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN);
11085         mService.maybeShowInitialReviewPermissionsNotification();
11086         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11087     }
11088 
11089     @Test
11090     public void testMaybeShowReviewPermissionsNotification_shouldShow() {
11091         mService.setShowReviewPermissionsNotification(true);
11092         reset(mMockNm);
11093 
11094         // If state is SHOULD_SHOW, it ... should show
11095         Settings.Global.putInt(mContext.getContentResolver(),
11096                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11097                 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
11098         mService.maybeShowInitialReviewPermissionsNotification();
11099         verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
11100                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
11101                 any(Notification.class));
11102     }
11103 
11104     @Test
11105     public void testMaybeShowReviewPermissionsNotification_alreadyShown() {
11106         mService.setShowReviewPermissionsNotification(true);
11107         reset(mMockNm);
11108 
11109         // If state is either USER_INTERACTED or DISMISSED, we should not show this on boot
11110         Settings.Global.putInt(mContext.getContentResolver(),
11111                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11112                 NotificationManagerService.REVIEW_NOTIF_STATE_USER_INTERACTED);
11113         mService.maybeShowInitialReviewPermissionsNotification();
11114 
11115         Settings.Global.putInt(mContext.getContentResolver(),
11116                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11117                 NotificationManagerService.REVIEW_NOTIF_STATE_DISMISSED);
11118         mService.maybeShowInitialReviewPermissionsNotification();
11119 
11120         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11121     }
11122 
11123     @Test
11124     public void testMaybeShowReviewPermissionsNotification_reshown() {
11125         mService.setShowReviewPermissionsNotification(true);
11126         reset(mMockNm);
11127 
11128         // If we have re-shown the notification and the user did not subsequently interacted with
11129         // it, then make sure we show when trying on boot
11130         Settings.Global.putInt(mContext.getContentResolver(),
11131                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11132                 NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN);
11133         mService.maybeShowInitialReviewPermissionsNotification();
11134         verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
11135                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
11136                 any(Notification.class));
11137     }
11138 
11139     @Test
11140     public void testRescheduledReviewPermissionsNotification() {
11141         mService.setShowReviewPermissionsNotification(true);
11142         reset(mMockNm);
11143 
11144         // when rescheduled, the notification goes through the NotificationManagerInternal service
11145         // this call doesn't need to know anything about previously scheduled state -- if called,
11146         // it should send the notification & write the appropriate int to Settings
11147         mInternalService.sendReviewPermissionsNotification();
11148 
11149         // Notification should be sent
11150         verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
11151                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
11152                 any(Notification.class));
11153 
11154         // write STATE_RESHOWN to settings
11155         assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN,
11156                 Settings.Global.getInt(mContext.getContentResolver(),
11157                         Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
11158                         NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN));
11159     }
11160 
11161     @Test
11162     public void testRescheduledReviewPermissionsNotification_flagOff() {
11163         mService.setShowReviewPermissionsNotification(false);
11164         reset(mMockNm);
11165 
11166         // no notification should be sent if the flag is off
11167         mInternalService.sendReviewPermissionsNotification();
11168         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
11169     }
11170 
11171     private void verifyStickyHun(Flag flag, int permissionState, boolean appRequested,
11172             boolean isSticky) throws Exception {
11173 
11174         when(mPermissionHelper.hasRequestedPermission(Manifest.permission.USE_FULL_SCREEN_INTENT,
11175                 PKG, mUserId)).thenReturn(appRequested);
11176 
11177         mTestFlagResolver.setFlagOverride(flag, true);
11178 
11179         when(mPermissionManager.checkPermissionForDataDelivery(
11180                 eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any()))
11181                 .thenReturn(permissionState);
11182 
11183         Notification n = new Notification.Builder(mContext, "test")
11184                 .setFullScreenIntent(mock(PendingIntent.class), true)
11185                 .build();
11186 
11187         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11188 
11189         final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
11190 
11191         if (isSticky) {
11192             assertNotSame(0, stickyFlag);
11193         } else {
11194             assertSame(0, stickyFlag);
11195         }
11196     }
11197 
11198     @Test
11199     public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun()
11200             throws Exception {
11201 
11202         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11203                 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true,
11204                 /* isSticky= */ true);
11205     }
11206 
11207     @Test
11208     public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun()
11209             throws Exception {
11210 
11211         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11212                 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true,
11213                 /* isSticky= */ true);
11214     }
11215 
11216     @Test
11217     public void testFixNotification_fsiPermissionSoftDenied_appNotRequest_noShowStickyHun()
11218             throws Exception {
11219         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11220                 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, false,
11221                 /* isSticky= */ false);
11222     }
11223 
11224 
11225     @Test
11226     public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi()
11227             throws Exception {
11228 
11229         verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
11230                 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true,
11231                 /* isSticky= */ false);
11232     }
11233 
11234     @Test
11235     public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun()
11236             throws Exception {
11237 
11238         verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
11239                 /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED, true,
11240                 /* isSticky= */ true);
11241     }
11242 
11243     @Test
11244     public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun()
11245             throws Exception {
11246 
11247         verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
11248                 /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED, true,
11249                 /* isSticky= */ true);
11250     }
11251 
11252     @Test
11253     public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun()
11254             throws Exception {
11255 
11256         verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
11257                 /* permissionState= */ PermissionManager.PERMISSION_GRANTED, true,
11258                 /* isSticky= */ true);
11259     }
11260 
11261     @Test
11262     public void fixNotification_withFgsFlag_butIsNotFgs() throws Exception {
11263         final ApplicationInfo applicationInfo = new ApplicationInfo();
11264         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11265                 .thenReturn(applicationInfo);
11266 
11267         Notification n = new Notification.Builder(mContext, "test")
11268                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
11269                 .setFlag(FLAG_CAN_COLORIZE, true)
11270                 .build();
11271 
11272         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11273 
11274         assertFalse(n.isForegroundService());
11275         assertFalse(n.hasColorizedPermission());
11276     }
11277 
11278     @Test
11279     public void checkCallStyleNotification_withoutAnyValidUseCase_throws() throws Exception {
11280         Person person = new Person.Builder().setName("caller").build();
11281         Notification n = new Notification.Builder(mContext, "test")
11282                 .setStyle(Notification.CallStyle.forOngoingCall(
11283                         person, mock(PendingIntent.class)))
11284                 .build();
11285         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11286                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11287         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11288 
11289         try {
11290             mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11291                     r.getSbn().getId(), r.getSbn().getTag(), r, false, false);
11292             assertFalse("CallStyle should not be allowed without a valid use case", true);
11293         } catch (IllegalArgumentException error) {
11294             assertThat(error.getMessage()).contains("CallStyle");
11295         }
11296     }
11297 
11298     @Test
11299     public void checkCallStyleNotification_allowedForFgs() throws Exception {
11300         Person person = new Person.Builder().setName("caller").build();
11301         Notification n = new Notification.Builder(mContext, "test")
11302                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
11303                 .setStyle(Notification.CallStyle.forOngoingCall(
11304                         person, mock(PendingIntent.class)))
11305                 .build();
11306         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11307                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11308         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11309 
11310         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11311                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11312     }
11313 
11314     @Test
11315     public void checkCallStyleNotification_allowedForByForegroundService() throws Exception {
11316         Person person = new Person.Builder().setName("caller").build();
11317         Notification n = new Notification.Builder(mContext, "test")
11318                 // Without FLAG_FOREGROUND_SERVICE.
11319                 //.setFlag(FLAG_FOREGROUND_SERVICE, true)
11320                 .setStyle(Notification.CallStyle.forOngoingCall(
11321                         person, mock(PendingIntent.class)))
11322                 .build();
11323         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11324                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11325         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11326 
11327         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11328                 r.getSbn().getId(), r.getSbn().getTag(), r, false,
11329                 true /* byForegroundService */)).isTrue();
11330     }
11331 
11332     @Test
11333     public void checkCallStyleNotification_allowedForUij() throws Exception {
11334         Person person = new Person.Builder().setName("caller").build();
11335         Notification n = new Notification.Builder(mContext, "test")
11336                 .setFlag(FLAG_USER_INITIATED_JOB, true)
11337                 .setStyle(Notification.CallStyle.forOngoingCall(
11338                         person, mock(PendingIntent.class)))
11339                 .build();
11340         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11341                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11342         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11343 
11344         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11345                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11346     }
11347 
11348     @Test
11349     public void checkCallStyleNotification_allowedForFsiAllowed() throws Exception {
11350         Person person = new Person.Builder().setName("caller").build();
11351         Notification n = new Notification.Builder(mContext, "test")
11352                 .setFullScreenIntent(mock(PendingIntent.class), true)
11353                 .setStyle(Notification.CallStyle.forOngoingCall(
11354                         person, mock(PendingIntent.class)))
11355                 .build();
11356         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11357                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11358         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11359 
11360         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11361                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11362     }
11363 
11364     @Test
11365     public void checkCallStyleNotification_allowedForFsiDenied() throws Exception {
11366         Person person = new Person.Builder().setName("caller").build();
11367         Notification n = new Notification.Builder(mContext, "test")
11368                 .setFlag(Notification.FLAG_FSI_REQUESTED_BUT_DENIED, true)
11369                 .setStyle(Notification.CallStyle.forOngoingCall(
11370                         person, mock(PendingIntent.class)))
11371                 .build();
11372         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
11373                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11374         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
11375 
11376         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
11377                 r.getSbn().getId(), r.getSbn().getTag(), r, false, false)).isTrue();
11378     }
11379 
11380     @Test
11381     public void fixSystemNotification_withOnGoingFlag_shouldBeDismissible()
11382             throws Exception {
11383         final ApplicationInfo ai = new ApplicationInfo();
11384         ai.packageName = "pkg";
11385         ai.uid = mUid;
11386         ai.flags |= ApplicationInfo.FLAG_SYSTEM;
11387 
11388         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11389                 .thenReturn(ai);
11390         when(mAppOpsManager.checkOpNoThrow(
11391                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
11392                 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED);
11393         // Given: a notification from an app on the system partition has the flag
11394         // FLAG_ONGOING_EVENT set
11395         Notification n = new Notification.Builder(mContext, "test")
11396                 .setOngoing(true)
11397                 .build();
11398 
11399         // When: fix the notification with NotificationManagerService
11400         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11401 
11402         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11403         assertSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11404     }
11405 
11406     @Test
11407     public void fixMediaNotification_withOnGoingFlag_shouldBeNonDismissible()
11408             throws Exception {
11409         // Given: a media notification has the flag FLAG_ONGOING_EVENT set
11410         Notification n = new Notification.Builder(mContext, "test")
11411                 .setOngoing(true)
11412                 .setStyle(new Notification.MediaStyle()
11413                         .setMediaSession(mock(MediaSession.Token.class)))
11414                 .build();
11415 
11416         // When: fix the notification with NotificationManagerService
11417         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11418 
11419         // Then: the notification's flag FLAG_NO_DISMISS should be set
11420         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11421     }
11422 
11423     @Test
11424     public void fixSystemNotification_defaultSearchSelectior_withOnGoingFlag_nondismissible()
11425             throws Exception {
11426         final ApplicationInfo ai = new ApplicationInfo();
11427         ai.packageName = SEARCH_SELECTOR_PKG;
11428         ai.uid = mUid;
11429         ai.flags |= ApplicationInfo.FLAG_SYSTEM;
11430 
11431         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11432                 .thenReturn(ai);
11433         when(mAppOpsManager.checkOpNoThrow(
11434                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
11435                 ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED);
11436         // Given: a notification from an app on the system partition has the flag
11437         // FLAG_ONGOING_EVENT set
11438         Notification n = new Notification.Builder(mContext, "test")
11439                 .setOngoing(true)
11440                 .build();
11441 
11442         // When: fix the notification with NotificationManagerService
11443         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11444 
11445         // Then: the notification's flag FLAG_NO_DISMISS should be set
11446         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11447     }
11448 
11449     @Test
11450     public void fixCallNotification_withOnGoingFlag_shouldNotBeNonDismissible()
11451             throws Exception {
11452         // Given: a call notification has the flag FLAG_ONGOING_EVENT set
11453         Person person = new Person.Builder()
11454                 .setName("caller")
11455                 .build();
11456         Notification n = new Notification.Builder(mContext, "test")
11457                 .setOngoing(true)
11458                 .setStyle(Notification.CallStyle.forOngoingCall(
11459                         person, mock(PendingIntent.class)))
11460                 .build();
11461 
11462         // When: fix the notification with NotificationManagerService
11463         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11464 
11465         // Then: the notification's flag FLAG_NO_DISMISS should be set
11466         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11467     }
11468 
11469 
11470     @Test
11471     public void fixNonExemptNotification_withOnGoingFlag_shouldBeDismissible() throws Exception {
11472         // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
11473         Notification n = new Notification.Builder(mContext, "test")
11474                 .setOngoing(true)
11475                 .build();
11476 
11477         // When: fix the notification with NotificationManagerService
11478         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11479 
11480         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11481         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11482     }
11483 
11484     @Test
11485     public void fixNonExemptNotification_withNoDismissFlag_shouldBeDismissible()
11486             throws Exception {
11487         // Given: a non-exempt notification has the flag FLAG_NO_DISMISS set (even though this is
11488         // not allowed)
11489         Notification n = new Notification.Builder(mContext, "test")
11490                 .build();
11491         n.flags |= Notification.FLAG_NO_DISMISS;
11492 
11493         // When: fix the notification with NotificationManagerService
11494         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11495 
11496         // Then: the notification's flag FLAG_NO_DISMISS should be cleared
11497         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11498     }
11499 
11500     @Test
11501     public void fixMediaNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
11502         // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set
11503         Notification n = new Notification.Builder(mContext, "test")
11504                 .setOngoing(false)
11505                 .setStyle(new Notification.MediaStyle()
11506                         .setMediaSession(mock(MediaSession.Token.class)))
11507                 .build();
11508 
11509         // When: fix the notification with NotificationManagerService
11510         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11511 
11512         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11513         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11514     }
11515 
11516     @Test
11517     public void fixMediaNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible()
11518             throws Exception {
11519         // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set,
11520         // but has the flag FLAG_NO_DISMISS set
11521         Notification n = new Notification.Builder(mContext, "test")
11522                 .setOngoing(false)
11523                 .setStyle(new Notification.MediaStyle()
11524                         .setMediaSession(mock(MediaSession.Token.class)))
11525                 .build();
11526         n.flags |= Notification.FLAG_NO_DISMISS;
11527 
11528         // When: fix the notification with NotificationManagerService
11529         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11530 
11531         // Then: the notification's flag FLAG_NO_DISMISS should be cleared
11532         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11533     }
11534 
11535     @Test
11536     public void fixNonExempt_Notification_withoutOnGoingFlag_shouldBeDismissible()
11537             throws Exception {
11538         // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
11539         Notification n = new Notification.Builder(mContext, "test")
11540                 .setOngoing(false)
11541                 .build();
11542 
11543         // When: fix the notification with NotificationManagerService
11544         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11545 
11546         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11547         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11548     }
11549 
11550     @Test
11551     public void fixOrganizationAdminNotification_withOnGoingFlag_shouldBeNonDismissible()
11552             throws Exception {
11553         when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true);
11554         // Given: a notification has the flag FLAG_ONGOING_EVENT set
11555         setDpmAppOppsExemptFromDismissal(false);
11556         Notification n = new Notification.Builder(mContext, "test")
11557                 .setOngoing(true)
11558                 .build();
11559 
11560         // When: fix the notification with NotificationManagerService
11561         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11562 
11563         // Then: the notification's flag FLAG_NO_DISMISS should be set
11564         assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11565     }
11566 
11567     @Test
11568     public void fixExemptAppOpNotification_withFlag_shouldBeNonDismissible()
11569             throws Exception {
11570         final ApplicationInfo ai = new ApplicationInfo();
11571         ai.packageName = PKG;
11572         ai.uid = mUid;
11573         ai.flags |= ApplicationInfo.FLAG_SYSTEM;
11574 
11575         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
11576                 .thenReturn(ai);
11577         when(mAppOpsManager.checkOpNoThrow(
11578                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
11579                 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
11580         // Given: a notification has the flag FLAG_ONGOING_EVENT set
11581         setDpmAppOppsExemptFromDismissal(true);
11582         Notification n = new Notification.Builder(mContext, "test")
11583                 .setOngoing(true)
11584                 .build();
11585 
11586         // When: fix the notification with NotificationManagerService
11587         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11588 
11589         // Then: the notification's flag FLAG_NO_DISMISS should be cleared
11590         assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
11591     }
11592 
11593     @Test
11594     public void fixExemptAppOpNotification_withoutAppOpsFlag_shouldBeDismissible()
11595             throws Exception {
11596         when(mAppOpsManager.checkOpNoThrow(
11597                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
11598                 PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
11599         // Given: a notification has the flag FLAG_ONGOING_EVENT set
11600         setDpmAppOppsExemptFromDismissal(false);
11601         Notification n = new Notification.Builder(mContext, "test")
11602                 .setOngoing(true)
11603                 .build();
11604 
11605         // When: fix the notification with NotificationManagerService
11606         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
11607 
11608         // Then: the notification's flag FLAG_NO_DISMISS should not be set
11609         assertSame(0, n.flags & Notification.FLAG_NO_DISMISS);
11610     }
11611 
11612     @Test
11613     public void testCancelAllNotifications_IgnoreUserInitiatedJob() throws Exception {
11614         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11615                 .thenReturn(true);
11616         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11617         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11618         mBinderService.enqueueNotificationWithTag(PKG, PKG,
11619                 "testCancelAllNotifications_IgnoreUserInitiatedJob",
11620                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11621         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
11622         waitForIdle();
11623         StatusBarNotification[] notifs =
11624                 mBinderService.getActiveNotifications(sbn.getPackageName());
11625         assertEquals(1, notifs.length);
11626         assertEquals(1, mService.getNotificationRecordCount());
11627     }
11628 
11629     @Test
11630     public void testCancelAllNotifications_UijFlag_NoUij_Allowed() throws Exception {
11631         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11632                 .thenReturn(false);
11633         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11634         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11635         mBinderService.enqueueNotificationWithTag(PKG, PKG,
11636                 "testCancelAllNotifications_UijFlag_NoUij_Allowed",
11637                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11638         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
11639         waitForIdle();
11640         StatusBarNotification[] notifs =
11641                 mBinderService.getActiveNotifications(sbn.getPackageName());
11642         assertEquals(0, notifs.length);
11643     }
11644 
11645     @Test
11646     public void testCancelAllNotificationsOtherPackage_IgnoresUijNotification() throws Exception {
11647         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11648                 .thenReturn(true);
11649         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11650         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11651         mBinderService.enqueueNotificationWithTag(PKG, PKG,
11652                 "testCancelAllNotifications_IgnoreOtherPackages",
11653                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11654         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
11655         waitForIdle();
11656         StatusBarNotification[] notifs =
11657                 mBinderService.getActiveNotifications(sbn.getPackageName());
11658         assertEquals(1, notifs.length);
11659         assertEquals(1, mService.getNotificationRecordCount());
11660     }
11661 
11662     @Test
11663     public void testRemoveUserInitiatedJobFlag_ImmediatelyAfterEnqueue() throws Exception {
11664         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11665                 .thenReturn(true);
11666         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
11667                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
11668                 .build();
11669         StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
11670                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
11671         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11672         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
11673                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11674         mInternalService.removeUserInitiatedJobFlagFromNotification(PKG, sbn.getId(),
11675                 sbn.getUserId());
11676         waitForIdle();
11677         StatusBarNotification[] notifs =
11678                 mBinderService.getActiveNotifications(sbn.getPackageName());
11679         assertFalse(notifs[0].getNotification().isUserInitiatedJob());
11680     }
11681 
11682     @Test
11683     public void testCancelAfterSecondEnqueueDoesNotSpecifyUserInitiatedJobFlag() throws Exception {
11684         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
11685         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT | FLAG_USER_INITIATED_JOB;
11686         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
11687                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11688         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
11689         mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
11690                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
11691         mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
11692                 sbn.getUserId());
11693         waitForIdle();
11694         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
11695         assertEquals(0, mService.getNotificationRecordCount());
11696     }
11697 
11698     @Test
11699     public void testCancelNotificationWithTag_fromApp_cannotCancelUijChild() throws Exception {
11700         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11701                 .thenReturn(true);
11702         mService.isSystemUid = false;
11703         mService.isSystemAppId = false;
11704         final NotificationRecord parent = generateNotificationRecord(
11705                 mTestNotificationChannel, 1, "group", true);
11706         final NotificationRecord child = generateNotificationRecord(
11707                 mTestNotificationChannel, 2, "group", false);
11708         final NotificationRecord child2 = generateNotificationRecord(
11709                 mTestNotificationChannel, 3, "group", false);
11710         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11711         mService.addNotification(parent);
11712         mService.addNotification(child);
11713         mService.addNotification(child2);
11714         mService.getBinderService().cancelNotificationWithTag(
11715                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
11716                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
11717         waitForIdle();
11718         StatusBarNotification[] notifs =
11719                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11720         assertEquals(1, notifs.length);
11721     }
11722 
11723     @Test
11724     public void testCancelNotificationWithTag_fromApp_cannotCancelUijParent() throws Exception {
11725         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11726                 .thenReturn(true);
11727         mService.isSystemUid = false;
11728         mService.isSystemAppId = false;
11729         final NotificationRecord parent = generateNotificationRecord(
11730                 mTestNotificationChannel, 1, "group", true);
11731         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11732         final NotificationRecord child = generateNotificationRecord(
11733                 mTestNotificationChannel, 2, "group", false);
11734         final NotificationRecord child2 = generateNotificationRecord(
11735                 mTestNotificationChannel, 3, "group", false);
11736         mService.addNotification(parent);
11737         mService.addNotification(child);
11738         mService.addNotification(child2);
11739         mService.getBinderService().cancelNotificationWithTag(
11740                 parent.getSbn().getPackageName(), parent.getSbn().getPackageName(),
11741                 parent.getSbn().getTag(), parent.getSbn().getId(), parent.getSbn().getUserId());
11742         waitForIdle();
11743         StatusBarNotification[] notifs =
11744                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11745         assertEquals(3, notifs.length);
11746     }
11747 
11748     @Test
11749     public void testCancelAllNotificationsFromApp_cannotCancelUijChild() throws Exception {
11750         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11751                 .thenReturn(true);
11752         mService.isSystemUid = false;
11753         mService.isSystemAppId = false;
11754         final NotificationRecord parent = generateNotificationRecord(
11755                 mTestNotificationChannel, 1, "group", true);
11756         final NotificationRecord child = generateNotificationRecord(
11757                 mTestNotificationChannel, 2, "group", false);
11758         final NotificationRecord child2 = generateNotificationRecord(
11759                 mTestNotificationChannel, 3, "group", false);
11760         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11761         final NotificationRecord newGroup = generateNotificationRecord(
11762                 mTestNotificationChannel, 4, "group2", false);
11763         mService.addNotification(parent);
11764         mService.addNotification(child);
11765         mService.addNotification(child2);
11766         mService.addNotification(newGroup);
11767         mService.getBinderService().cancelAllNotifications(
11768                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
11769         waitForIdle();
11770         StatusBarNotification[] notifs =
11771                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11772         assertEquals(1, notifs.length);
11773     }
11774 
11775     @Test
11776     public void testCancelAllNotifications_fromApp_cannotCancelUijParent() throws Exception {
11777         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11778                 .thenReturn(true);
11779         mService.isSystemUid = false;
11780         mService.isSystemAppId = false;
11781         final NotificationRecord parent = generateNotificationRecord(
11782                 mTestNotificationChannel, 1, "group", true);
11783         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11784         final NotificationRecord child = generateNotificationRecord(
11785                 mTestNotificationChannel, 2, "group", false);
11786         final NotificationRecord child2 = generateNotificationRecord(
11787                 mTestNotificationChannel, 3, "group", false);
11788         final NotificationRecord newGroup = generateNotificationRecord(
11789                 mTestNotificationChannel, 4, "group2", false);
11790         mService.addNotification(parent);
11791         mService.addNotification(child);
11792         mService.addNotification(child2);
11793         mService.addNotification(newGroup);
11794         mService.getBinderService().cancelAllNotifications(
11795                 parent.getSbn().getPackageName(), parent.getSbn().getUserId());
11796         waitForIdle();
11797         StatusBarNotification[] notifs =
11798                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11799         assertEquals(1, notifs.length);
11800     }
11801 
11802     @Test
11803     public void testCancelNotificationsFromListener_clearAll_GroupWithUijParent() throws Exception {
11804         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11805                 .thenReturn(true);
11806         final NotificationRecord parent = generateNotificationRecord(
11807                 mTestNotificationChannel, 1, "group", true);
11808         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11809         final NotificationRecord child = generateNotificationRecord(
11810                 mTestNotificationChannel, 2, "group", false);
11811         final NotificationRecord child2 = generateNotificationRecord(
11812                 mTestNotificationChannel, 3, "group", false);
11813         final NotificationRecord newGroup = generateNotificationRecord(
11814                 mTestNotificationChannel, 4, "group2", false);
11815         mService.addNotification(parent);
11816         mService.addNotification(child);
11817         mService.addNotification(child2);
11818         mService.addNotification(newGroup);
11819         mService.getBinderService().cancelNotificationsFromListener(null, null);
11820         waitForIdle();
11821         StatusBarNotification[] notifs =
11822                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11823         assertEquals(0, notifs.length);
11824     }
11825 
11826     @Test
11827     public void testCancelNotificationsFromListener_clearAll_GroupWithUijChild() throws Exception {
11828         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11829                 .thenReturn(true);
11830         final NotificationRecord parent = generateNotificationRecord(
11831                 mTestNotificationChannel, 1, "group", true);
11832         final NotificationRecord child = generateNotificationRecord(
11833                 mTestNotificationChannel, 2, "group", false);
11834         final NotificationRecord child2 = generateNotificationRecord(
11835                 mTestNotificationChannel, 3, "group", false);
11836         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11837         final NotificationRecord newGroup = generateNotificationRecord(
11838                 mTestNotificationChannel, 4, "group2", false);
11839         mService.addNotification(parent);
11840         mService.addNotification(child);
11841         mService.addNotification(child2);
11842         mService.addNotification(newGroup);
11843         mService.getBinderService().cancelNotificationsFromListener(null, null);
11844         waitForIdle();
11845         StatusBarNotification[] notifs =
11846                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11847         assertEquals(0, notifs.length);
11848     }
11849 
11850     @Test
11851     public void testCancelNotificationsFromListener_clearAll_Uij() throws Exception {
11852         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11853                 .thenReturn(true);
11854         final NotificationRecord child2 = generateNotificationRecord(
11855                 mTestNotificationChannel, 3, null, false);
11856         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11857         mService.addNotification(child2);
11858         mService.getBinderService().cancelNotificationsFromListener(null, null);
11859         waitForIdle();
11860         StatusBarNotification[] notifs =
11861                 mBinderService.getActiveNotifications(child2.getSbn().getPackageName());
11862         assertEquals(0, notifs.length);
11863     }
11864 
11865     @Test
11866     public void testCancelNotificationsFromListener_byKey_GroupWithUijParent() throws Exception {
11867         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11868                 .thenReturn(true);
11869         final NotificationRecord parent = generateNotificationRecord(
11870                 mTestNotificationChannel, 1, "group", true);
11871         parent.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11872         final NotificationRecord child = generateNotificationRecord(
11873                 mTestNotificationChannel, 2, "group", false);
11874         final NotificationRecord child2 = generateNotificationRecord(
11875                 mTestNotificationChannel, 3, "group", false);
11876         final NotificationRecord newGroup = generateNotificationRecord(
11877                 mTestNotificationChannel, 4, "group2", false);
11878         mService.addNotification(parent);
11879         mService.addNotification(child);
11880         mService.addNotification(child2);
11881         mService.addNotification(newGroup);
11882         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
11883                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
11884         mService.getBinderService().cancelNotificationsFromListener(null, keys);
11885         waitForIdle();
11886         StatusBarNotification[] notifs =
11887                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11888         assertEquals(0, notifs.length);
11889     }
11890 
11891     @Test
11892     public void testCancelNotificationsFromListener_byKey_GroupWithUijChild() throws Exception {
11893         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11894                 .thenReturn(true);
11895         final NotificationRecord parent = generateNotificationRecord(
11896                 mTestNotificationChannel, 1, "group", true);
11897         final NotificationRecord child = generateNotificationRecord(
11898                 mTestNotificationChannel, 2, "group", false);
11899         final NotificationRecord child2 = generateNotificationRecord(
11900                 mTestNotificationChannel, 3, "group", false);
11901         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11902         final NotificationRecord newGroup = generateNotificationRecord(
11903                 mTestNotificationChannel, 4, "group2", false);
11904         mService.addNotification(parent);
11905         mService.addNotification(child);
11906         mService.addNotification(child2);
11907         mService.addNotification(newGroup);
11908         String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
11909                 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
11910         mService.getBinderService().cancelNotificationsFromListener(null, keys);
11911         waitForIdle();
11912         StatusBarNotification[] notifs =
11913                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11914         assertEquals(0, notifs.length);
11915     }
11916 
11917     @Test
11918     public void testCancelNotificationsFromListener_byKey_Uij() throws Exception {
11919         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11920                 .thenReturn(true);
11921         final NotificationRecord child = generateNotificationRecord(
11922                 mTestNotificationChannel, 3, null, false);
11923         child.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11924         mService.addNotification(child);
11925         String[] keys = {child.getSbn().getKey()};
11926         mService.getBinderService().cancelNotificationsFromListener(null, keys);
11927         waitForIdle();
11928         StatusBarNotification[] notifs =
11929                 mBinderService.getActiveNotifications(child.getSbn().getPackageName());
11930         assertEquals(0, notifs.length);
11931     }
11932 
11933     @Test
11934     public void testUserInitiatedCancelAllWithGroup_UserInitiatedFlag() throws Exception {
11935         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
11936                 .thenReturn(true);
11937         final NotificationRecord parent = generateNotificationRecord(
11938                 mTestNotificationChannel, 1, "group", true);
11939         final NotificationRecord child = generateNotificationRecord(
11940                 mTestNotificationChannel, 2, "group", false);
11941         final NotificationRecord child2 = generateNotificationRecord(
11942                 mTestNotificationChannel, 3, "group", false);
11943         child2.getNotification().flags |= FLAG_USER_INITIATED_JOB;
11944         final NotificationRecord newGroup = generateNotificationRecord(
11945                 mTestNotificationChannel, 4, "group2", false);
11946         mService.addNotification(parent);
11947         mService.addNotification(child);
11948         mService.addNotification(child2);
11949         mService.addNotification(newGroup);
11950         mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(), parent.getUserId());
11951         waitForIdle();
11952         StatusBarNotification[] notifs =
11953                 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
11954         assertEquals(0, notifs.length);
11955     }
11956 
11957     @Test
11958     public void testDeleteChannelGroupChecksForUijs() throws Exception {
11959         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
11960                 .thenReturn(singletonList(mock(AssociationInfo.class)));
11961         CountDownLatch latch = new CountDownLatch(2);
11962         mService.createNotificationChannelGroup(PKG, mUid,
11963                 new NotificationChannelGroup("group", "group"), true, false);
11964         new Thread(() -> {
11965             NotificationChannel notificationChannel = new NotificationChannel("id", "id",
11966                     NotificationManager.IMPORTANCE_HIGH);
11967             notificationChannel.setGroup("group");
11968             ParceledListSlice<NotificationChannel> pls =
11969                     new ParceledListSlice(ImmutableList.of(notificationChannel));
11970             try {
11971                 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
11972             } catch (RemoteException e) {
11973                 throw new RuntimeException(e);
11974             }
11975             latch.countDown();
11976         }).start();
11977         new Thread(() -> {
11978             try {
11979                 synchronized (this) {
11980                     wait(5000);
11981                 }
11982                 mService.createNotificationChannelGroup(PKG, mUid,
11983                         new NotificationChannelGroup("new", "new group"), true, false);
11984                 NotificationChannel notificationChannel =
11985                         new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
11986                 notificationChannel.setGroup("new");
11987                 ParceledListSlice<NotificationChannel> pls =
11988                         new ParceledListSlice(ImmutableList.of(notificationChannel));
11989                 try {
11990                     mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
11991                     mBinderService.deleteNotificationChannelGroup(PKG, "group");
11992                 } catch (RemoteException e) {
11993                     throw new RuntimeException(e);
11994                 }
11995             } catch (Exception e) {
11996                 e.printStackTrace();
11997             }
11998             latch.countDown();
11999         }).start();
12000 
12001         latch.await();
12002         verify(mJsi).isNotificationChannelAssociatedWithAnyUserInitiatedJobs(
12003                 anyString(), anyInt(), anyString());
12004     }
12005 
12006     @Test
12007     public void testRemoveUserInitiatedJobFlagFromNotification_enqueued() {
12008         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12009                 .thenReturn(true);
12010         Notification n = new Notification.Builder(mContext, "").build();
12011         n.flags |= FLAG_USER_INITIATED_JOB;
12012 
12013         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
12014                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12015         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12016 
12017         mService.addEnqueuedNotification(r);
12018 
12019         mInternalService.removeUserInitiatedJobFlagFromNotification(
12020                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12021 
12022         waitForIdle();
12023 
12024         verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
12025     }
12026 
12027     @Test
12028     public void testRemoveUserInitiatedJobFlagFromNotification_posted() {
12029         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12030                 .thenReturn(true);
12031         Notification n = new Notification.Builder(mContext, "").build();
12032         n.flags |= FLAG_USER_INITIATED_JOB;
12033 
12034         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
12035                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12036         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12037 
12038         mService.addNotification(r);
12039 
12040         mInternalService.removeUserInitiatedJobFlagFromNotification(
12041                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12042 
12043         waitForIdle();
12044 
12045         ArgumentCaptor<NotificationRecord> captor =
12046                 ArgumentCaptor.forClass(NotificationRecord.class);
12047         verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
12048 
12049         assertEquals(0, captor.getValue().getNotification().flags);
12050     }
12051 
12052     @Test
12053     public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_enqueued() {
12054         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12055             Notification n = new Notification.Builder(mContext, "").build();
12056             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
12057                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
12058             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12059             mService.addEnqueuedNotification(r);
12060         }
12061         Notification n = new Notification.Builder(mContext, "").build();
12062         n.flags |= FLAG_USER_INITIATED_JOB;
12063 
12064         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
12065                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
12066                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12067         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12068 
12069         mService.addEnqueuedNotification(r);
12070 
12071         mInternalService.removeUserInitiatedJobFlagFromNotification(
12072                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12073 
12074         waitForIdle();
12075 
12076         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
12077                 mService.getNotificationRecordCount());
12078     }
12079 
12080     @Test
12081     public void testCannotRemoveUserInitiatedJobFlagWhenOverLimit_posted() {
12082         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12083                 .thenReturn(true);
12084         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12085             Notification n = new Notification.Builder(mContext, "").build();
12086             StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
12087                     n, UserHandle.getUserHandleForUid(mUid), null, 0);
12088             NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12089             mService.addNotification(r);
12090         }
12091         Notification n = new Notification.Builder(mContext, "").build();
12092         n.flags |= FLAG_USER_INITIATED_JOB;
12093 
12094         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG,
12095                 NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS, null, mUid, 0,
12096                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
12097         NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
12098 
12099         mService.addNotification(r);
12100 
12101         mInternalService.removeUserInitiatedJobFlagFromNotification(
12102                 PKG, r.getSbn().getId(), r.getSbn().getUserId());
12103 
12104         waitForIdle();
12105 
12106         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS,
12107                 mService.getNotificationRecordCount());
12108     }
12109 
12110     @Test
12111     public void testCanPostUijWhenOverLimit() throws RemoteException {
12112         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12113                 .thenReturn(true);
12114         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12115             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
12116                     i, null, false).getSbn();
12117             mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCanPostUijWhenOverLimit",
12118                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
12119         }
12120 
12121         final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
12122         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12123         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12124                 "testCanPostUijWhenOverLimit - uij over limit!",
12125                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
12126 
12127         waitForIdle();
12128 
12129         StatusBarNotification[] notifs =
12130                 mBinderService.getActiveNotifications(sbn.getPackageName());
12131         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
12132         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
12133                 mService.getNotificationRecordCount());
12134     }
12135 
12136     @Test
12137     public void testCannotPostNonUijWhenOverLimit() throws RemoteException {
12138         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12139                 .thenReturn(true);
12140         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
12141             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
12142                     i, null, false).getSbn();
12143             mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCannotPostNonUijWhenOverLimit",
12144                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
12145             waitForIdle();
12146         }
12147 
12148         final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
12149                 100, null, false).getSbn();
12150         sbn.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12151         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12152                 "testCannotPostNonUijWhenOverLimit - uij over limit!",
12153                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
12154 
12155         final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
12156                 101, null, false).getSbn();
12157         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12158                 "testCannotPostNonUijWhenOverLimit - non uij over limit!",
12159                 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
12160 
12161         when(mJsi.isNotificationAssociatedWithAnyUserInitiatedJobs(anyInt(), anyInt(), anyString()))
12162                 .thenReturn(false);
12163         final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel,
12164                 101, null, false).getSbn();
12165         sbn3.getNotification().flags |= FLAG_USER_INITIATED_JOB;
12166         mBinderService.enqueueNotificationWithTag(PKG, PKG,
12167                 "testCannotPostNonUijWhenOverLimit - fake uij over limit!",
12168                 sbn3.getId(), sbn3.getNotification(), sbn3.getUserId());
12169 
12170         waitForIdle();
12171 
12172         StatusBarNotification[] notifs =
12173                 mBinderService.getActiveNotifications(sbn.getPackageName());
12174         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
12175         assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
12176                 mService.getNotificationRecordCount());
12177     }
12178 
12179     @Test
12180     public void fixNotification_withUijFlag_butIsNotUij() throws Exception {
12181         final ApplicationInfo applicationInfo = new ApplicationInfo();
12182         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
12183                 .thenReturn(applicationInfo);
12184 
12185         Notification n = new Notification.Builder(mContext, "test")
12186                 .setFlag(FLAG_USER_INITIATED_JOB, true)
12187                 .build();
12188 
12189         mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
12190         assertFalse(n.isUserInitiatedJob());
12191     }
12192 
12193     @Test
12194     public void enqueue_updatesEnqueueRate() throws Exception {
12195         Notification n = generateNotificationRecord(null).getNotification();
12196 
12197         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
12198         // Don't waitForIdle() here. We want to verify the "intermediate" state.
12199 
12200         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12201         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12202         verify(mUsageStats, never()).registerPostedByApp(any());
12203 
12204         waitForIdle();
12205     }
12206 
12207     @Test
12208     public void enqueue_withPost_updatesEnqueueRateAndPost() throws Exception {
12209         Notification n = generateNotificationRecord(null).getNotification();
12210 
12211         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
12212         waitForIdle();
12213 
12214         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12215         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12216         verify(mUsageStats).registerPostedByApp(any());
12217     }
12218 
12219     @Test
12220     public void enqueueNew_whenOverEnqueueRate_accepts() throws Exception {
12221         Notification n = generateNotificationRecord(null).getNotification();
12222         when(mUsageStats.getAppEnqueueRate(eq(PKG)))
12223                 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f);
12224 
12225         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
12226         waitForIdle();
12227 
12228         assertThat(mService.mNotificationsByKey).hasSize(1);
12229         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12230         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12231         verify(mUsageStats).registerPostedByApp(any());
12232     }
12233 
12234     @Test
12235     public void enqueueUpdate_whenBelowMaxEnqueueRate_accepts() throws Exception {
12236         // Post the first version.
12237         Notification original = generateNotificationRecord(null).getNotification();
12238         original.when = 111;
12239         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId);
12240         waitForIdle();
12241         assertThat(mService.mNotificationList).hasSize(1);
12242         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111);
12243 
12244         reset(mUsageStats);
12245         when(mUsageStats.getAppEnqueueRate(eq(PKG)))
12246                 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE - 1f);
12247 
12248         // Post the update.
12249         Notification update = generateNotificationRecord(null).getNotification();
12250         update.when = 222;
12251         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId);
12252         waitForIdle();
12253 
12254         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12255         verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
12256         verify(mUsageStats, never()).registerPostedByApp(any());
12257         verify(mUsageStats).registerUpdatedByApp(any(), any());
12258         assertThat(mService.mNotificationList).hasSize(1);
12259         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(222);
12260     }
12261 
12262     @Test
12263     public void enqueueUpdate_whenAboveMaxEnqueueRate_rejects() throws Exception {
12264         // Post the first version.
12265         Notification original = generateNotificationRecord(null).getNotification();
12266         original.when = 111;
12267         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId);
12268         waitForIdle();
12269         assertThat(mService.mNotificationList).hasSize(1);
12270         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111);
12271 
12272         reset(mUsageStats);
12273         when(mUsageStats.getAppEnqueueRate(eq(PKG)))
12274                 .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f);
12275 
12276         // Post the update.
12277         Notification update = generateNotificationRecord(null).getNotification();
12278         update.when = 222;
12279         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId);
12280         waitForIdle();
12281 
12282         verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
12283         verify(mUsageStats, never()).registerEnqueuedByAppAndAccepted(any());
12284         verify(mUsageStats, never()).registerPostedByApp(any());
12285         verify(mUsageStats, never()).registerUpdatedByApp(any(), any());
12286         assertThat(mService.mNotificationList).hasSize(1);
12287         assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); // old
12288     }
12289 
12290     @Test
12291     public void enqueueNotification_allowlistsPendingIntents() throws RemoteException {
12292         PendingIntent contentIntent = createPendingIntent("content");
12293         PendingIntent actionIntent1 = createPendingIntent("action1");
12294         PendingIntent actionIntent2 = createPendingIntent("action2");
12295         Notification n = new Notification.Builder(mContext, TEST_CHANNEL_ID)
12296                 .setContentIntent(contentIntent)
12297                 .addAction(new Notification.Action.Builder(null, "action1", actionIntent1).build())
12298                 .addAction(new Notification.Action.Builder(null, "action2", actionIntent2).build())
12299                 .build();
12300 
12301         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1,
12302                 parcelAndUnparcel(n, Notification.CREATOR), mUserId);
12303 
12304         verify(mAmi, times(3)).setPendingIntentAllowlistDuration(
12305                 any(), any(), anyLong(),
12306                 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED),
12307                 eq(REASON_NOTIFICATION_SERVICE), any());
12308         verify(mAmi, times(3)).setPendingIntentAllowBgActivityStarts(any(),
12309                 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
12310     }
12311 
12312     @Test
12313     public void enqueueNotification_allowlistsPendingIntents_includingFromPublicVersion()
12314             throws RemoteException {
12315         PendingIntent contentIntent = createPendingIntent("content");
12316         PendingIntent actionIntent = createPendingIntent("action");
12317         PendingIntent publicContentIntent = createPendingIntent("publicContent");
12318         PendingIntent publicActionIntent = createPendingIntent("publicAction");
12319         Notification source = new Notification.Builder(mContext, TEST_CHANNEL_ID)
12320                 .setContentIntent(contentIntent)
12321                 .addAction(new Notification.Action.Builder(null, "action", actionIntent).build())
12322                 .setPublicVersion(new Notification.Builder(mContext, "channel")
12323                         .setContentIntent(publicContentIntent)
12324                         .addAction(new Notification.Action.Builder(
12325                                 null, "publicAction", publicActionIntent).build())
12326                         .build())
12327                 .build();
12328 
12329         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 1,
12330                 parcelAndUnparcel(source, Notification.CREATOR), mUserId);
12331 
12332         verify(mAmi, times(4)).setPendingIntentAllowlistDuration(
12333                 any(), any(), anyLong(),
12334                 eq(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED),
12335                 eq(REASON_NOTIFICATION_SERVICE), any());
12336         verify(mAmi, times(4)).setPendingIntentAllowBgActivityStarts(any(),
12337                 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
12338     }
12339 
12340     @Test
12341     public void onUserSwitched_updatesZenModeAndChannelsBypassingDnd() {
12342         Intent intent = new Intent(Intent.ACTION_USER_SWITCHED);
12343         intent.putExtra(Intent.EXTRA_USER_HANDLE, 20);
12344         mService.mZenModeHelper = mock(ZenModeHelper.class);
12345         mService.setPreferencesHelper(mPreferencesHelper);
12346 
12347         mUserSwitchIntentReceiver.onReceive(mContext, intent);
12348 
12349         InOrder inOrder = inOrder(mPreferencesHelper, mService.mZenModeHelper);
12350         inOrder.verify(mService.mZenModeHelper).onUserSwitched(eq(20));
12351         inOrder.verify(mPreferencesHelper).syncChannelsBypassingDnd();
12352         inOrder.verifyNoMoreInteractions();
12353     }
12354 
12355     @Test
12356     public void isNotificationPolicyAccessGranted_invalidPackage() throws Exception {
12357         final String notReal = "NOT REAL";
12358         final var checker = mService.permissionChecker;
12359 
12360         when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
12361                 PackageManager.NameNotFoundException.class);
12362 
12363         assertThat(mBinderService.isNotificationPolicyAccessGranted(notReal)).isFalse();
12364         verify(mPackageManagerClient).getPackageUidAsUser(eq(notReal), anyInt());
12365         verify(checker, never()).check(any(), anyInt(), anyInt(), anyBoolean());
12366         verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(notReal), anyInt());
12367         verify(mListeners, never()).isComponentEnabledForPackage(any());
12368         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12369     }
12370 
12371     @Test
12372     public void isNotificationPolicyAccessGranted_hasPermission() throws Exception {
12373         final String packageName = "target";
12374         final int uid = 123;
12375         final var checker = mService.permissionChecker;
12376 
12377         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12378         when(checker.check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true))
12379                 .thenReturn(PackageManager.PERMISSION_GRANTED);
12380 
12381         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12382         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12383         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12384         verify(mConditionProviders, never()).isPackageOrComponentAllowed(eq(packageName), anyInt());
12385         verify(mListeners, never()).isComponentEnabledForPackage(any());
12386         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12387     }
12388 
12389     @Test
12390     public void isNotificationPolicyAccessGranted_isPackageAllowed() throws Exception {
12391         final String packageName = "target";
12392         final int uid = 123;
12393         final var checker = mService.permissionChecker;
12394 
12395         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12396         when(mConditionProviders.isPackageOrComponentAllowed(eq(packageName), anyInt()))
12397                 .thenReturn(true);
12398 
12399         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12400         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12401         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12402         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12403         verify(mListeners, never()).isComponentEnabledForPackage(any());
12404         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12405     }
12406 
12407     @Test
12408     public void isNotificationPolicyAccessGranted_isComponentEnabled() throws Exception {
12409         final String packageName = "target";
12410         final int uid = 123;
12411         final var checker = mService.permissionChecker;
12412 
12413         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12414         when(mListeners.isComponentEnabledForPackage(packageName)).thenReturn(true);
12415 
12416         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12417         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12418         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12419         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12420         verify(mListeners).isComponentEnabledForPackage(packageName);
12421         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(anyInt());
12422     }
12423 
12424     @Test
12425     public void isNotificationPolicyAccessGranted_isDeviceOwner() throws Exception {
12426         final String packageName = "target";
12427         final int uid = 123;
12428         final var checker = mService.permissionChecker;
12429 
12430         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12431         when(mDevicePolicyManager.isActiveDeviceOwner(uid)).thenReturn(true);
12432 
12433         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isTrue();
12434         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12435         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12436         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12437         verify(mListeners).isComponentEnabledForPackage(packageName);
12438         verify(mDevicePolicyManager).isActiveDeviceOwner(uid);
12439     }
12440 
12441     /**
12442      * b/292163859
12443      */
12444     @Test
12445     public void isNotificationPolicyAccessGranted_callerIsDeviceOwner() throws Exception {
12446         final String packageName = "target";
12447         final int uid = 123;
12448         final int callingUid = Binder.getCallingUid();
12449         final var checker = mService.permissionChecker;
12450 
12451         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12452         when(mDevicePolicyManager.isActiveDeviceOwner(callingUid)).thenReturn(true);
12453 
12454         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse();
12455         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12456         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12457         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12458         verify(mListeners).isComponentEnabledForPackage(packageName);
12459         verify(mDevicePolicyManager).isActiveDeviceOwner(uid);
12460         verify(mDevicePolicyManager, never()).isActiveDeviceOwner(callingUid);
12461     }
12462 
12463     @Test
12464     public void isNotificationPolicyAccessGranted_notGranted() throws Exception {
12465         final String packageName = "target";
12466         final int uid = 123;
12467         final var checker = mService.permissionChecker;
12468 
12469         when(mPackageManagerClient.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid);
12470 
12471         assertThat(mBinderService.isNotificationPolicyAccessGranted(packageName)).isFalse();
12472         verify(mPackageManagerClient).getPackageUidAsUser(eq(packageName), anyInt());
12473         verify(checker).check(android.Manifest.permission.MANAGE_NOTIFICATIONS, uid, -1, true);
12474         verify(mConditionProviders).isPackageOrComponentAllowed(eq(packageName), anyInt());
12475         verify(mListeners).isComponentEnabledForPackage(packageName);
12476         verify(mDevicePolicyManager).isActiveDeviceOwner(uid);
12477     }
12478 
12479     private static <T extends Parcelable> T parcelAndUnparcel(T source,
12480             Parcelable.Creator<T> creator) {
12481         Parcel parcel = Parcel.obtain();
12482         source.writeToParcel(parcel, 0);
12483         parcel.setDataPosition(0);
12484         return creator.createFromParcel(parcel);
12485     }
12486 
12487     private PendingIntent createPendingIntent(String action) {
12488         return PendingIntent.getActivity(mContext, 0,
12489                 new Intent(action).setPackage(mContext.getPackageName()),
12490                 PendingIntent.FLAG_MUTABLE);
12491     }
12492 
12493     private void setDpmAppOppsExemptFromDismissal(boolean isOn) {
12494         DeviceConfig.setProperty(
12495                 DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
12496                 /* name= */ "application_exemptions",
12497                 String.valueOf(isOn),
12498                 /* makeDefault= */ false);
12499     }
12500 
12501     private void allowTestPackageToToast() throws Exception {
12502         assertWithMessage("toast queue").that(mService.mToastQueue).isEmpty();
12503         mService.isSystemUid = false;
12504         mService.isSystemAppId = false;
12505         setToastRateIsWithinQuota(true);
12506         setIfPackageHasPermissionToAvoidToastRateLimiting(TEST_PACKAGE, false);
12507         // package is not suspended
12508         when(mPackageManager.isPackageSuspendedForUser(TEST_PACKAGE, mUserId))
12509                 .thenReturn(false);
12510     }
12511 
12512     private void enqueueToast(String testPackage, ITransientNotification callback)
12513             throws RemoteException {
12514         enqueueToast((INotificationManager) mService.mService, testPackage, new Binder(), callback);
12515     }
12516 
12517     private void enqueueToast(INotificationManager service, String testPackage,
12518             IBinder token, ITransientNotification callback) throws RemoteException {
12519         service.enqueueToast(testPackage, token, callback, TOAST_DURATION, /* isUiContext= */ true,
12520                 DEFAULT_DISPLAY);
12521     }
12522 
12523     private void enqueueTextToast(String testPackage, CharSequence text) throws RemoteException {
12524         enqueueTextToast(testPackage, text, /* isUiContext= */ true, DEFAULT_DISPLAY);
12525     }
12526 
12527     private void enqueueTextToast(String testPackage, CharSequence text, boolean isUiContext,
12528             int displayId) throws RemoteException {
12529         ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), text,
12530                 TOAST_DURATION, isUiContext, displayId, /* textCallback= */ null);
12531     }
12532 
12533     private void mockIsVisibleBackgroundUsersSupported(boolean supported) {
12534         when(mUm.isVisibleBackgroundUsersSupported()).thenReturn(supported);
12535     }
12536 
12537     private void mockIsUserVisible(int displayId, boolean visible) {
12538         when(mUmInternal.isUserVisible(mUserId, displayId)).thenReturn(visible);
12539     }
12540 
12541     private void mockDisplayAssignedToUser(int displayId) {
12542         when(mUmInternal.getMainDisplayAssignedToUser(mUserId)).thenReturn(displayId);
12543     }
12544 
12545     private void verifyToastShownForTestPackage(String text, int displayId) {
12546         verify(mStatusBar).showToast(eq(mUid), eq(TEST_PACKAGE), any(), eq(text), any(),
12547                 eq(TOAST_DURATION), any(), eq(displayId));
12548     }
12549 }
12550