blob: 0c31b143df57c34439e2816e452a5aa0560dd42c [file] [log] [blame]
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05001/*
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
17package com.android.server.notification;
18
Beverly58b24532018-10-02 09:08:23 -040019import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
20import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
Mady Mellorbe797962019-04-01 16:04:24 -070021import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
22import static android.app.Notification.CATEGORY_CALL;
Mady Mellor49b1bf12019-03-29 12:00:02 -070023import static android.app.Notification.FLAG_BUBBLE;
Julia Reynoldse5c60452018-04-30 14:41:36 -040024import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050025import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
Julia Reynolds27c0a962018-12-10 12:37:28 -050026import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040027import static android.app.NotificationManager.IMPORTANCE_HIGH;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040028import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050029import static android.app.NotificationManager.IMPORTANCE_MAX;
Julia Reynolds4da79702017-06-01 11:06:10 -040030import static android.app.NotificationManager.IMPORTANCE_NONE;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040031import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050032import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
33import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
34import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
35import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
36import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
37import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
38import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
39import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
40import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
Julia Reynoldse1816412017-10-24 10:39:11 -040041import static android.content.pm.PackageManager.FEATURE_WATCH;
Julia Reynolds4db59552017-06-30 13:34:01 -040042import static android.content.pm.PackageManager.PERMISSION_DENIED;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -040043import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050044import static android.os.Build.VERSION_CODES.O_MR1;
45import static android.os.Build.VERSION_CODES.P;
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -040046import static android.service.notification.Adjustment.KEY_IMPORTANCE;
47import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
Tony Makeda84a72018-11-19 17:01:32 +000048import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
49import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040050
Geoffrey Pitsch03533712017-01-05 10:30:07 -050051import static junit.framework.Assert.assertEquals;
Julia Reynolds727a7282017-04-13 10:54:01 -040052import static junit.framework.Assert.assertFalse;
Julia Reynolds92febc32017-10-26 11:30:31 -040053import static junit.framework.Assert.assertNotNull;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040054import static junit.framework.Assert.assertNull;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050055import static junit.framework.Assert.assertTrue;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050056import static junit.framework.Assert.fail;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050057
Julia Reynolds5f20e9f2017-01-30 08:54:53 -050058import static org.mockito.Matchers.anyBoolean;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -040059import static org.mockito.Matchers.anyLong;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050060import static org.mockito.Matchers.anyString;
61import static org.mockito.Matchers.eq;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050062import static org.mockito.Mockito.any;
63import static org.mockito.Mockito.anyInt;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040064import static org.mockito.Mockito.doAnswer;
Julia Reynolds4afe2642019-05-01 08:42:24 -040065import static org.mockito.Mockito.doNothing;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050066import static org.mockito.Mockito.mock;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040067import static org.mockito.Mockito.never;
68import static org.mockito.Mockito.reset;
Julia Reynolds503ed942017-10-04 16:04:56 -040069import static org.mockito.Mockito.spy;
70import static org.mockito.Mockito.timeout;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050071import static org.mockito.Mockito.times;
72import static org.mockito.Mockito.verify;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050073import static org.mockito.Mockito.when;
74
Julia Reynolds68263d12017-06-21 14:21:19 -040075import android.app.ActivityManager;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -040076import android.app.AppOpsManager;
Julia Reynoldsa94365d2019-04-09 10:48:43 -040077import android.app.AutomaticZenRule;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040078import android.app.IActivityManager;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050079import android.app.INotificationManager;
Julia Reynolds268647a2018-10-25 16:54:27 -040080import android.app.ITransientNotification;
81import android.app.IUriGrantsManager;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050082import android.app.Notification;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040083import android.app.Notification.MessagingStyle.Message;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050084import android.app.NotificationChannel;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040085import android.app.NotificationChannelGroup;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050086import android.app.NotificationManager;
Mady Mellor7eb18ef2019-03-27 14:03:46 -070087import android.app.PendingIntent;
Mady Mellorbe797962019-04-01 16:04:24 -070088import android.app.Person;
Mady Mellora10448e2019-04-26 13:50:58 -070089import android.app.RemoteInput;
Jason Parks50322ff2018-03-27 10:23:33 -050090import android.app.admin.DevicePolicyManagerInternal;
Julia Reynolds7217dc92018-03-07 12:12:09 -050091import android.app.usage.UsageStatsManagerInternal;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040092import android.companion.ICompanionDeviceManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -050093import android.content.ComponentName;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -060094import android.content.ContentUris;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050095import android.content.Context;
Beverlyd4f96492017-08-02 13:36:11 -040096import android.content.Intent;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050097import android.content.pm.ApplicationInfo;
98import android.content.pm.IPackageManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -050099import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500100import android.content.pm.ParceledListSlice;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400101import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200102import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400103import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700104import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400105import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400106import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500107import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400108import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400109import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400110import android.os.IBinder;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400111import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400112import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700113import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500114import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400115import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000116import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600117import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000118import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400119import android.service.notification.Adjustment;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400120import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400121import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500122import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400123import android.service.notification.ZenPolicy;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400124import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400125import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400126import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400127import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400128import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400129import android.testing.TestablePermissions;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400130import android.text.Html;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400131import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000132import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400133import android.util.AtomicFile;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400134
Mady Mellor49b1bf12019-03-29 12:00:02 -0700135import androidx.annotation.Nullable;
136import androidx.test.InstrumentationRegistry;
137
Kristian Monsen05f34792018-04-09 10:27:16 +0200138import com.android.internal.R;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000139import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Julia Reynolds503ed942017-10-04 16:04:56 -0400140import com.android.internal.statusbar.NotificationVisibility;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700141import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400142import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500143import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400144import com.android.server.lights.Light;
145import com.android.server.lights.LightsManager;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400146import com.android.server.notification.NotificationManagerService.NotificationAssistants;
147import com.android.server.notification.NotificationManagerService.NotificationListeners;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700148import com.android.server.uri.UriGrantsManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400149import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400150
151import org.junit.After;
152import org.junit.Before;
153import org.junit.Test;
154import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500155import org.mockito.ArgumentCaptor;
156import org.mockito.Mock;
157import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400158import org.mockito.stubbing.Answer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500159
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400160import java.io.BufferedInputStream;
161import java.io.ByteArrayInputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400162import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400163import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400164import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500165import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000166import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400167import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400168import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200169import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500170
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400171@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400172@RunWith(AndroidTestingRunner.class)
173@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500174public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500175 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000176 private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
177 "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
178 + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
179 private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD =
180 "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
181 + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
182
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400183 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500184 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500185 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400186 private NotificationManagerInternal mInternalService;
Julia Reynoldsda781472017-04-12 09:41:16 -0400187 @Mock
188 private IPackageManager mPackageManager;
189 @Mock
190 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400191 @Mock
192 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400193 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500194 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400195 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400196 @Mock
197 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400198 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400199 AtomicFile mPolicyFile;
200 File mFile;
201 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400202 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400203 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400204 private UsageStatsManagerInternal mAppUsageStats;
205 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400206 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400207 @Mock
208 ActivityManager mActivityManager;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400209 NotificationManagerService.WorkerHandler mHandler;
Kristian Monsen05f34792018-04-09 10:27:16 +0200210 @Mock
211 Resources mResources;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400212
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500213 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500214 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000215
216 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
217
Julia Reynoldsda781472017-04-12 09:41:16 -0400218 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400219 private NotificationListeners mListeners;
220 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400221 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400222 private ManagedServices.ManagedServiceInfo mListener;
223 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400224 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400225 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400226 @Mock
227 IBinder mPermOwner;
228 @Mock
229 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700230 @Mock
231 IUriGrantsManager mUgm;
232 @Mock
233 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400234 @Mock
235 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000236 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000237 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
238 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400239 @Mock
240 UserManager mUm;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500241
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400242 // Use a Testable subclass so we can simulate calls from the system without failing.
243 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500244 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700245 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000246 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000247 @Nullable
248 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500249
Julia Reynolds0c245002019-03-27 16:10:11 -0400250 TestableNotificationManagerService(Context context) {
Amith Yamasani803eab692017-11-09 17:47:04 -0800251 super(context);
252 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400253
254 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400255 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500256 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700257 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400258 }
259
260 @Override
261 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500262 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700263 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400264 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400265
266 @Override
267 protected ICompanionDeviceManager getCompanionManager() {
268 return null;
269 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800270
271 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800272 protected void reportUserInteraction(NotificationRecord r) {
273 return;
274 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500275
276 @Override
277 protected void handleSavePolicyFile() {
278 return;
279 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000280
281 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000282 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
283 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000284 countLogSmartSuggestionsVisible++;
285 }
286
Annie Meng8b646fd2019-02-01 18:46:42 +0000287 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000288 protected void setNotificationAssistantAccessGrantedForUserInternal(
289 ComponentName assistant, int userId, boolean granted) {
290 if (mNotificationAssistantAccessGrantedCallback != null) {
291 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
292 return;
293 }
294 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
295 }
296
297 private void setNotificationAssistantAccessGrantedCallback(
298 @Nullable NotificationAssistantAccessGrantedCallback callback) {
299 this.mNotificationAssistantAccessGrantedCallback = callback;
300 }
301
302 interface NotificationAssistantAccessGrantedCallback {
303 void onGranted(ComponentName assistant, int userId, boolean granted);
304 }
305
Mady Mellorca0c24c2019-05-16 16:14:32 -0700306 @Override
307 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
308 String packageName) {
309 // Tests for this not being true are in CTS NotificationManagerTest
310 return true;
311 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400312 }
313
Beverly58b24532018-10-02 09:08:23 -0400314 private class TestableToastCallback extends ITransientNotification.Stub {
315 @Override
316 public void show(IBinder windowToken) {
317 }
318
319 @Override
320 public void hide() {
321 }
322 }
323
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500324 @Before
325 public void setUp() throws Exception {
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000326 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
327 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
328
Julia Reynoldsda781472017-04-12 09:41:16 -0400329 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400330
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700331 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
332 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400333 LocalServices.removeServiceForTest(WindowManagerInternal.class);
334 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700335
Julia Reynolds4afe2642019-05-01 08:42:24 -0400336 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
337
Julia Reynolds0c245002019-03-27 16:10:11 -0400338 mService = new TestableNotificationManagerService(mContext);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500339
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400340 // Use this testable looper.
341 mTestableLooper = TestableLooper.get(this);
Julia Reynolds503ed942017-10-04 16:04:56 -0400342 mHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500343 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400344 mContext.setMockPackageManager(mPackageManagerClient);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500345 final ApplicationInfo applicationInfo = new ApplicationInfo();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400346 applicationInfo.uid = mUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400347 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500348 .thenReturn(applicationInfo);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500349 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500350 .thenReturn(applicationInfo);
Julia Reynolds92febc32017-10-26 11:30:31 -0400351 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500352 final LightsManager mockLightsManager = mock(LightsManager.class);
353 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400354 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400355 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700356 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400357 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400358 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400359 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500360
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400361 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400362 mFile = new File(mContext.getCacheDir(), "test.xml");
363 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400364 final String preupgradeXml = "<notification-policy></notification-policy>";
365 mPolicyFile = new AtomicFile(mFile);
366 FileOutputStream fos = mPolicyFile.startWrite();
367 fos.write(preupgradeXml.getBytes());
368 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400369
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400370 // Setup managed services
371 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400372 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400373 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
374 ManagedServices.Config listenerConfig = new ManagedServices.Config();
375 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
376 when(mListeners.getConfig()).thenReturn(listenerConfig);
377 ManagedServices.Config assistantConfig = new ManagedServices.Config();
378 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
379 when(mAssistants.getConfig()).thenReturn(assistantConfig);
380 ManagedServices.Config dndConfig = new ManagedServices.Config();
381 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
382 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
383
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400384 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
385
Julia Reynolds4afe2642019-05-01 08:42:24 -0400386
387 mService.init(mTestableLooper.getLooper(),
388 mPackageManager, mPackageManagerClient, mockLightsManager,
389 mListeners, mAssistants, mConditionProviders,
390 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
391 mGroupHelper, mAm, mAppUsageStats,
392 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
393 mAppOpsManager, mUm);
394 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
395
Julia Reynolds503ed942017-10-04 16:04:56 -0400396 mService.setAudioManager(mAudioManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500397
398 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400399 mBinderService = mService.getBinderService();
400 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500401
402 mBinderService.createNotificationChannels(
403 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400404 assertNotNull(mBinderService.getNotificationChannel(
405 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500406 }
407
Julia Reynoldsb852e562017-06-06 16:14:18 -0400408 @After
409 public void tearDown() throws Exception {
410 mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000411 clearDeviceConfig();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000412 InstrumentationRegistry.getInstrumentation()
413 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400414 }
415
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500416 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400417 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500418 }
419
Mady Mellorc6820342019-05-20 12:04:36 -0700420 private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
421 boolean channelEnabled) {
422 mService.setPreferencesHelper(mPreferencesHelper);
423 when(mPreferencesHelper.bubblesEnabled(any())).thenReturn(globalEnabled);
424 when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
425 when(mPreferencesHelper.getNotificationChannel(
426 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
427 mTestNotificationChannel);
428 when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
429 mTestNotificationChannel.getImportance());
430 mTestNotificationChannel.setAllowBubbles(channelEnabled);
431 }
432
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500433 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
434 Notification.Builder nb = new Notification.Builder(mContext, "a")
435 .setContentTitle("foo")
436 .setSmallIcon(android.R.drawable.sym_def_app_icon);
437 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0,
438 nb.build(), new UserHandle(userId), null, postTime);
439 return sbn;
440 }
441
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400442 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
443 String groupKey, boolean isSummary) {
444 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
445 .setContentTitle("foo")
446 .setSmallIcon(android.R.drawable.sym_def_app_icon)
447 .setGroup(groupKey)
448 .setGroupSummary(isSummary);
449
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400450 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
451 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000452 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400453 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400454
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500455 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500456 return generateNotificationRecord(channel, null);
457 }
458
459 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
460 Notification.TvExtender extender) {
Mady Mellorbe797962019-04-01 16:04:24 -0700461 return generateNotificationRecord(channel, extender, false /* isBubble */);
462 }
463
464 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
465 Notification.TvExtender extender, boolean isBubble) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500466 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500467 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500468 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500469 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500470 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500471 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500472 if (extender != null) {
473 nb.extend(extender);
474 }
Mady Mellorbe797962019-04-01 16:04:24 -0700475 if (isBubble) {
476 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
477 }
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400478 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
479 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000480 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500481 }
482
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400483 private Map<String, Answer> getSignalExtractorSideEffects() {
484 Map<String, Answer> answers = new ArrayMap<>();
485
486 answers.put("override group key", invocationOnMock -> {
487 ((NotificationRecord) invocationOnMock.getArguments()[0])
488 .setOverrideGroupKey("bananas");
489 return null;
490 });
491 answers.put("override people", invocationOnMock -> {
492 ((NotificationRecord) invocationOnMock.getArguments()[0])
493 .setPeopleOverride(new ArrayList<>());
494 return null;
495 });
496 answers.put("snooze criteria", invocationOnMock -> {
497 ((NotificationRecord) invocationOnMock.getArguments()[0])
498 .setSnoozeCriteria(new ArrayList<>());
499 return null;
500 });
501 answers.put("notification channel", invocationOnMock -> {
502 ((NotificationRecord) invocationOnMock.getArguments()[0])
503 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
504 return null;
505 });
506 answers.put("badging", invocationOnMock -> {
507 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
508 r.setShowBadge(!r.canShowBadge());
509 return null;
510 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500511 answers.put("bubbles", invocationOnMock -> {
512 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
513 r.setAllowBubble(!r.canBubble());
514 return null;
515 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400516 answers.put("package visibility", invocationOnMock -> {
517 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
518 Notification.VISIBILITY_SECRET);
519 return null;
520 });
521
522 return answers;
523 }
524
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400525 private void clearDeviceConfig() {
526 DeviceConfig.resetToDefaults(
527 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
528 }
529
530 private void setDefaultAssistantInDeviceConfig(String componentName) {
531 DeviceConfig.setProperty(
532 DeviceConfig.NAMESPACE_SYSTEMUI,
533 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
534 componentName,
535 false);
536 }
537
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700538 private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() {
539 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
540 return new Notification.BubbleMetadata.Builder()
541 .setIntent(pi)
542 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
543 }
544
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500545 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500546 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500547 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500548 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400549 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500550 new ParceledListSlice(Arrays.asList(channel)));
551 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400552 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500553 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500554 }
555
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500556 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500557 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500558 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400559 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200560 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500561 fail("Exception should be thrown immediately.");
562 } catch (NullPointerException e) {
563 // pass
564 }
565 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500566
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500567 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500568 public void testCreateNotificationChannels_TwoChannels() throws Exception {
569 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500570 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500571 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500572 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400573 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500574 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400575 assertTrue(mBinderService.getNotificationChannel(
576 PKG, mContext.getUserId(), PKG, "id1") != null);
577 assertTrue(mBinderService.getNotificationChannel(
578 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500579 }
580
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500581 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400582 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
583 throws Exception {
584 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500585 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400586 mBinderService.createNotificationChannels(PKG,
587 new ParceledListSlice(Arrays.asList(channel)));
588
589 // Recreating the channel doesn't throw, but ignores importance.
590 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400591 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400592 mBinderService.createNotificationChannels(PKG,
593 new ParceledListSlice(Arrays.asList(dupeChannel)));
594 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400595 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500596 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400597 }
598
599 @Test
600 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
601 throws Exception {
602 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500603 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400604 mBinderService.createNotificationChannels(PKG,
605 new ParceledListSlice(Arrays.asList(channel)));
606
607 // Recreating with a lower importance is allowed to modify the channel.
608 final NotificationChannel dupeChannel =
609 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
610 mBinderService.createNotificationChannels(PKG,
611 new ParceledListSlice(Arrays.asList(dupeChannel)));
612 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400613 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400614 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
615 }
616
617 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400618 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
619 throws Exception {
620 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500621 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400622 mBinderService.createNotificationChannels(PKG,
623 new ParceledListSlice(Arrays.asList(channel)));
624
625 // The user modifies importance directly, can no longer be changed by the app.
626 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400627 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400628 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
629
630 // Recreating with a lower importance leaves channel unchanged.
631 final NotificationChannel dupeChannel =
632 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
633 mBinderService.createNotificationChannels(PKG,
634 new ParceledListSlice(Arrays.asList(dupeChannel)));
635 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400636 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400637 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400638 }
639
640 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500641 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
642 throws Exception {
643 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500644 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500645 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400646 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400647 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500648 new ParceledListSlice(Arrays.asList(channel1, channel2)));
649 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400650 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500651 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500652 }
653
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500654 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500655 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500656 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
657
658 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400659 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500660 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400661
662 // isBlocked is only used for user blocking, not app suspension
663 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500664 }
665
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500666 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500667 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500668 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
669
670 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400671 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500672 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400673 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400674 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400675
676 mBinderService.createNotificationChannels(
677 PKG, new ParceledListSlice(Arrays.asList(channel)));
678 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400679 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400680 sbn.getId(), sbn.getNotification(), sbn.getUserId());
681 waitForIdle();
682 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
683 }
684
685 @Test
686 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
687 throws Exception {
688 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
689
690 NotificationChannel channel = new NotificationChannel("blocked", "name",
691 NotificationManager.IMPORTANCE_NONE);
692 mBinderService.createNotificationChannels(
693 PKG, new ParceledListSlice(Arrays.asList(channel)));
694
695 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400696 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400697 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400698 sbn.getId(), sbn.getNotification(), sbn.getUserId());
699 waitForIdle();
700 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
701 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400702 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400703 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
704 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400705 }
706
707 @Test
708 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
709 throws Exception {
710 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
711
712 NotificationChannel channel =
713 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
714 mBinderService.createNotificationChannels(
715 PKG, new ParceledListSlice(Arrays.asList(channel)));
716
717 NotificationChannel update =
718 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
719 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
720 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400721 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
722 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400723
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700724 StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400725 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400726 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400727 sbn.getId(), sbn.getNotification(), sbn.getUserId());
728 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700729 // The first time a foreground service notification is shown, we allow the channel
730 // to be updated to allow it to be seen.
731 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
732 assertEquals(IMPORTANCE_LOW,
733 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400734 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
735 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700736 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
737 waitForIdle();
738
739 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
740 update.setFgServiceShown(true);
741 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
742 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400743 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
744 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700745
746 sbn = generateNotificationRecord(channel).sbn;
747 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400748 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700749 sbn.getId(), sbn.getNotification(), sbn.getUserId());
750 waitForIdle();
751 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400752 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400753 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400754 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
755 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500756 }
757
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500758 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -0400759 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
760 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400761 mService.setPreferencesHelper(mPreferencesHelper);
762 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400763
764 NotificationChannel channel = new NotificationChannel("id", "name",
765 NotificationManager.IMPORTANCE_HIGH);
766 channel.setGroup("something");
767 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400768 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -0400769 verify(mUsageStats, times(1)).registerBlocked(eq(r));
770 }
771
772 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -0400773 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500774 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
775
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400776 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -0400777
778 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400779 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds4da79702017-06-01 11:06:10 -0400780 sbn.getId(), sbn.getNotification(), sbn.getUserId());
781 waitForIdle();
782 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500783 }
784
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500785 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400786 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
787 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
788
789 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
790
791 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400792 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400793 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400794 sbn.getId(), sbn.getNotification(), sbn.getUserId());
795 waitForIdle();
796 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400797 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400798 }
799
Brad Stenning8c991ea2018-07-31 13:33:01 -0700800 /**
801 * Confirm the system user on automotive devices can use car categories
802 */
803 @Test
804 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
805 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
806 .thenReturn(true);
807 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
808 Notification.CATEGORY_CAR_WARNING,
809 Notification.CATEGORY_CAR_INFORMATION);
810 int id = 0;
811 for (String category: categories) {
812 final StatusBarNotification sbn =
813 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
814 sbn.getNotification().category = category;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400815 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700816 sbn.getId(), sbn.getNotification(), sbn.getUserId());
817 }
818 waitForIdle();
819 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
820 }
821
822
823 /**
824 * Confirm restricted notification categories only apply to automotive.
825 */
826 @Test
827 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
828 mService.isSystemUid = false;
829 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
830 .thenReturn(false);
831 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
832 Notification.CATEGORY_CAR_WARNING,
833 Notification.CATEGORY_CAR_INFORMATION);
834 int id = 0;
835 for (String category: categories) {
836 final StatusBarNotification sbn =
837 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
838 sbn.getNotification().category = category;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400839 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700840 sbn.getId(), sbn.getNotification(), sbn.getUserId());
841 }
842 waitForIdle();
843 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
844 }
845
846 /**
847 * Confirm if a non-system user tries to use the car categories on a automotive device that
848 * they will get a security exception
849 */
850 @Test
851 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
852 mService.isSystemUid = false;
853 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
854 .thenReturn(true);
855 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
856 Notification.CATEGORY_CAR_WARNING,
857 Notification.CATEGORY_CAR_INFORMATION);
858 for (String category: categories) {
859 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
860 sbn.getNotification().category = category;
861 try {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400862 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700863 sbn.getId(), sbn.getNotification(), sbn.getUserId());
864 fail("Calls from non system apps should not allow use of restricted categories");
865 } catch (SecurityException e) {
866 // pass
867 }
868 }
869 waitForIdle();
870 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
871 }
872
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400873 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400874 public void testBlockedNotifications_blockedByAssistant() throws Exception {
875 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500876 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400877
878 NotificationChannel channel = new NotificationChannel("id", "name",
879 NotificationManager.IMPORTANCE_HIGH);
880 NotificationRecord r = generateNotificationRecord(channel);
881 mService.addEnqueuedNotification(r);
882
Julia Reynolds27c0a962018-12-10 12:37:28 -0500883 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400884 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500885 Adjustment adjustment = new Adjustment(
886 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
887 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400888
889 NotificationManagerService.PostNotificationRunnable runnable =
890 mService.new PostNotificationRunnable(r.getKey());
891 runnable.run();
892 waitForIdle();
893
894 verify(mUsageStats, never()).registerPostedByApp(any());
895 }
896
897 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500898 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400899 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400900 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500901 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -0400902 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500903 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400904 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500905 }
906
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500907 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500908 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400909 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400910 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500911 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500912 waitForIdle();
913 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500914 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500915 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400916 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500917 }
918
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500919 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500920 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400921 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400922 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500923 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400924 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400925 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500926 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500927 waitForIdle();
928 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500929 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500930 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400931 assertEquals(0, mService.getNotificationRecordCount());
932 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
933 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
934 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500935 }
936
937 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500938 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -0400939 NotificationRecord r = generateNotificationRecord(null);
940 final StatusBarNotification sbn = r.sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400941 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400942 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500943 mBinderService.cancelNotificationsFromListener(null, null);
944 waitForIdle();
945 StatusBarNotification[] notifs =
946 mBinderService.getActiveNotifications(sbn.getPackageName());
947 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400948 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500949 }
950
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500951 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500952 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
953 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400954 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400955 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500956 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500957 waitForIdle();
958 StatusBarNotification[] notifs =
959 mBinderService.getActiveNotifications(sbn.getPackageName());
960 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400961 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -0400962 }
963
964 @Test
965 public void testUserInitiatedClearAll_noLeak() throws Exception {
966 final NotificationRecord n = generateNotificationRecord(
967 mTestNotificationChannel, 1, "group", true);
968
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400969 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -0400970 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
971 waitForIdle();
972
Julia Reynolds503ed942017-10-04 16:04:56 -0400973 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -0400974 n.getUserId());
975 waitForIdle();
976 StatusBarNotification[] notifs =
977 mBinderService.getActiveNotifications(n.sbn.getPackageName());
978 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400979 assertEquals(0, mService.getNotificationRecordCount());
980 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
981 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
982 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -0400983 }
984
985 @Test
986 public void testCancelAllNotificationsCancelsChildren() throws Exception {
987 final NotificationRecord parent = generateNotificationRecord(
988 mTestNotificationChannel, 1, "group1", true);
989 final NotificationRecord child = generateNotificationRecord(
990 mTestNotificationChannel, 2, "group1", false);
991
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400992 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -0400993 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400994 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -0400995 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
996 waitForIdle();
997
998 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
999 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001000 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001001 }
1002
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001003 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001004 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1005 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1006 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001007 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001008 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1009 }
1010 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1011 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001012
Julia Reynolds503ed942017-10-04 16:04:56 -04001013 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001014 }
1015
1016 @Test
1017 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1018 final NotificationRecord parent = generateNotificationRecord(
1019 mTestNotificationChannel, 1, "group1", true);
1020 final NotificationRecord parentAsChild = generateNotificationRecord(
1021 mTestNotificationChannel, 1, "group1", false);
1022 final NotificationRecord child = generateNotificationRecord(
1023 mTestNotificationChannel, 2, "group1", false);
1024
1025 // fully post parent notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001026 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001027 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1028 waitForIdle();
1029
1030 // enqueue the child several times
1031 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001032 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001033 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1034 }
1035 // make the parent a child, which will cancel the child notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001036 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001037 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1038 parentAsChild.sbn.getUserId());
1039 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001040
Julia Reynolds503ed942017-10-04 16:04:56 -04001041 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001042 }
1043
1044 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001045 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1046 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001047 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001048 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001049 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001050 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001051 waitForIdle();
1052 StatusBarNotification[] notifs =
1053 mBinderService.getActiveNotifications(sbn.getPackageName());
1054 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001055 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001056 }
1057
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001058 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001059 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1060 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001061 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001062 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001063 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001064 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1065 waitForIdle();
1066 StatusBarNotification[] notifs =
1067 mBinderService.getActiveNotifications(sbn.getPackageName());
1068 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001069 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001070 }
1071
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001072 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001073 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1074 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001075 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001076 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001077 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1078 waitForIdle();
1079 StatusBarNotification[] notifs =
1080 mBinderService.getActiveNotifications(sbn.getPackageName());
1081 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001082 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001083 }
1084
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001085 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001086 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1087 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001088 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001089 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001090 // Null pkg is how we signal a user switch.
1091 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1092 waitForIdle();
1093 StatusBarNotification[] notifs =
1094 mBinderService.getActiveNotifications(sbn.getPackageName());
1095 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001096 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001097 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001098
1099 @Test
Beverly40239d92017-07-07 10:20:41 -04001100 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1101 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1102 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001103 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Beverly40239d92017-07-07 10:20:41 -04001104 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1105 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1106 waitForIdle();
1107 StatusBarNotification[] notifs =
1108 mBinderService.getActiveNotifications(sbn.getPackageName());
1109 assertEquals(0, notifs.length);
1110 }
1111
1112 @Test
1113 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1114 final NotificationRecord notif = generateNotificationRecord(
1115 mTestNotificationChannel, 1, "group", true);
1116 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001117 mService.addNotification(notif);
1118 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001119 notif.getUserId(), 0, null);
1120 waitForIdle();
1121 StatusBarNotification[] notifs =
1122 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1123 assertEquals(0, notifs.length);
1124 }
1125
1126 @Test
1127 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1128 final NotificationRecord notif = generateNotificationRecord(
1129 mTestNotificationChannel, 1, "group", true);
1130 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001131 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001132
Julia Reynolds503ed942017-10-04 16:04:56 -04001133 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001134 notif.getUserId());
1135 waitForIdle();
1136 StatusBarNotification[] notifs =
1137 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1138 assertEquals(1, notifs.length);
1139 }
1140
1141 @Test
1142 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1143 final NotificationRecord parent = generateNotificationRecord(
1144 mTestNotificationChannel, 1, "group", true);
1145 final NotificationRecord child = generateNotificationRecord(
1146 mTestNotificationChannel, 2, "group", false);
1147 final NotificationRecord child2 = generateNotificationRecord(
1148 mTestNotificationChannel, 3, "group", false);
1149 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1150 final NotificationRecord newGroup = generateNotificationRecord(
1151 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001152 mService.addNotification(parent);
1153 mService.addNotification(child);
1154 mService.addNotification(child2);
1155 mService.addNotification(newGroup);
1156 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001157 waitForIdle();
1158 StatusBarNotification[] notifs =
1159 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1160 assertEquals(1, notifs.length);
1161 }
1162
1163 @Test
1164 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1165 final NotificationRecord parent = generateNotificationRecord(
1166 mTestNotificationChannel, 1, "group", true);
1167 final NotificationRecord child = generateNotificationRecord(
1168 mTestNotificationChannel, 2, "group", false);
1169 final NotificationRecord child2 = generateNotificationRecord(
1170 mTestNotificationChannel, 3, "group", false);
1171 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1172 final NotificationRecord newGroup = generateNotificationRecord(
1173 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001174 mService.addNotification(parent);
1175 mService.addNotification(child);
1176 mService.addNotification(child2);
1177 mService.addNotification(newGroup);
1178 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001179 parent.getUserId());
1180 waitForIdle();
1181 StatusBarNotification[] notifs =
1182 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1183 assertEquals(1, notifs.length);
1184 }
1185
1186 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001187 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
1188 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001189 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001190 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001191 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001192 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1193 sbn.getUserId());
1194 waitForIdle();
1195 StatusBarNotification[] notifs =
1196 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001197 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001198 }
1199
1200 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001201 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1202 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1203 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001204 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001205 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001206 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1207 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001208 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001209 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1210 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
1211 waitForIdle();
1212 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001213 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001214 }
1215
1216 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001217 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1218 throws Exception {
1219 final NotificationRecord parent = generateNotificationRecord(
1220 mTestNotificationChannel, 1, "group", true);
1221 final NotificationRecord child = generateNotificationRecord(
1222 mTestNotificationChannel, 2, "group", false);
1223 final NotificationRecord child2 = generateNotificationRecord(
1224 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001225 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001226 final NotificationRecord newGroup = generateNotificationRecord(
1227 mTestNotificationChannel, 4, "group2", false);
1228 mService.addNotification(parent);
1229 mService.addNotification(child);
1230 mService.addNotification(child2);
1231 mService.addNotification(newGroup);
1232 mService.getBinderService().cancelNotificationsFromListener(null, null);
1233 waitForIdle();
1234 StatusBarNotification[] notifs =
1235 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1236 assertEquals(0, notifs.length);
1237 }
1238
1239 @Test
1240 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1241 throws Exception {
1242 final NotificationRecord parent = generateNotificationRecord(
1243 mTestNotificationChannel, 1, "group", true);
1244 final NotificationRecord child = generateNotificationRecord(
1245 mTestNotificationChannel, 2, "group", false);
1246 final NotificationRecord child2 = generateNotificationRecord(
1247 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001248 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001249 final NotificationRecord newGroup = generateNotificationRecord(
1250 mTestNotificationChannel, 4, "group2", false);
1251 mService.addNotification(parent);
1252 mService.addNotification(child);
1253 mService.addNotification(child2);
1254 mService.addNotification(newGroup);
1255 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1256 child2.sbn.getKey(), newGroup.sbn.getKey()};
1257 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1258 waitForIdle();
1259 StatusBarNotification[] notifs =
1260 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1261 assertEquals(1, notifs.length);
1262 }
1263
1264 @Test
1265 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1266 final NotificationRecord parent = generateNotificationRecord(
1267 mTestNotificationChannel, 1, "group", true);
1268 final NotificationRecord child = generateNotificationRecord(
1269 mTestNotificationChannel, 2, "group", false);
1270 final NotificationRecord child2 = generateNotificationRecord(
1271 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001272 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001273 final NotificationRecord newGroup = generateNotificationRecord(
1274 mTestNotificationChannel, 4, "group2", false);
1275 mService.addNotification(parent);
1276 mService.addNotification(child);
1277 mService.addNotification(child2);
1278 mService.addNotification(newGroup);
1279 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1280 parent.getUserId());
1281 waitForIdle();
1282 StatusBarNotification[] notifs =
1283 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1284 assertEquals(0, notifs.length);
1285 }
1286
1287 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001288 public void testFindGroupNotificationsLocked() throws Exception {
1289 // make sure the same notification can be found in both lists and returned
1290 final NotificationRecord group1 = generateNotificationRecord(
1291 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001292 mService.addEnqueuedNotification(group1);
1293 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001294
1295 // should not be returned
1296 final NotificationRecord group2 = generateNotificationRecord(
1297 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001298 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001299 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1300 waitForIdle();
1301
1302 // should not be returned
1303 final NotificationRecord nonGroup = generateNotificationRecord(
1304 mTestNotificationChannel, 3, null, false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001305 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001306 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1307 waitForIdle();
1308
1309 // same group, child, should be returned
1310 final NotificationRecord group1Child = generateNotificationRecord(
1311 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001312 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001313 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1314 waitForIdle();
1315
1316 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001317 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001318 group1.sbn.getUserId());
1319 assertEquals(3, inGroup1.size());
1320 for (NotificationRecord record : inGroup1) {
1321 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1322 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1323 }
1324 }
1325
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001326 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001327 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1328 final NotificationRecord notif = generateNotificationRecord(
1329 mTestNotificationChannel, 1, "group", true);
1330 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1331 mService.addNotification(notif);
1332 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1333 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1334 waitForIdle();
1335 StatusBarNotification[] notifs =
1336 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1337 assertEquals(0, notifs.length);
1338 }
1339
1340 @Test
1341 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1342 throws Exception {
1343 final NotificationRecord parent = generateNotificationRecord(
1344 mTestNotificationChannel, 1, "group", true);
1345 final NotificationRecord child = generateNotificationRecord(
1346 mTestNotificationChannel, 2, "group", false);
1347 final NotificationRecord child2 = generateNotificationRecord(
1348 mTestNotificationChannel, 3, "group", false);
1349 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1350 final NotificationRecord newGroup = generateNotificationRecord(
1351 mTestNotificationChannel, 4, "group2", false);
1352 mService.addNotification(parent);
1353 mService.addNotification(child);
1354 mService.addNotification(child2);
1355 mService.addNotification(newGroup);
1356 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1357 child2.sbn.getKey(), newGroup.sbn.getKey()};
1358 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1359 waitForIdle();
1360 StatusBarNotification[] notifs =
1361 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1362 assertEquals(0, notifs.length);
1363 }
1364
1365 @Test
1366 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1367 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1368 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001369 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001370 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1371 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1372 waitForIdle();
1373 StatusBarNotification[] notifs =
1374 mBinderService.getActiveNotifications(sbn.getPackageName());
1375 assertEquals(0, notifs.length);
1376 }
1377
1378 @Test
1379 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1380 final NotificationRecord notif = generateNotificationRecord(
1381 mTestNotificationChannel, 1, "group", true);
1382 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1383 mService.addNotification(notif);
1384 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1385 notif.getUserId(), 0, null);
1386 waitForIdle();
1387 StatusBarNotification[] notifs =
1388 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1389 assertEquals(0, notifs.length);
1390 }
1391
1392 @Test
1393 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1394 final NotificationRecord notif = generateNotificationRecord(
1395 mTestNotificationChannel, 1, "group", true);
1396 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1397 mService.addNotification(notif);
1398
1399 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1400 notif.getUserId());
1401 waitForIdle();
1402 StatusBarNotification[] notifs =
1403 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1404 assertEquals(1, notifs.length);
1405 }
1406
1407 @Test
1408 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1409 final NotificationRecord parent = generateNotificationRecord(
1410 mTestNotificationChannel, 1, "group", true);
1411 final NotificationRecord child = generateNotificationRecord(
1412 mTestNotificationChannel, 2, "group", false);
1413 final NotificationRecord child2 = generateNotificationRecord(
1414 mTestNotificationChannel, 3, "group", false);
1415 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1416 final NotificationRecord newGroup = generateNotificationRecord(
1417 mTestNotificationChannel, 4, "group2", false);
1418 mService.addNotification(parent);
1419 mService.addNotification(child);
1420 mService.addNotification(child2);
1421 mService.addNotification(newGroup);
1422 mService.getBinderService().cancelNotificationsFromListener(null, null);
1423 waitForIdle();
1424 StatusBarNotification[] notifs =
1425 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1426 assertEquals(1, notifs.length);
1427 }
1428
1429 @Test
1430 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1431 throws Exception {
1432 final NotificationRecord parent = generateNotificationRecord(
1433 mTestNotificationChannel, 1, "group", true);
1434 final NotificationRecord child = generateNotificationRecord(
1435 mTestNotificationChannel, 2, "group", false);
1436 final NotificationRecord child2 = generateNotificationRecord(
1437 mTestNotificationChannel, 3, "group", false);
1438 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1439 final NotificationRecord newGroup = generateNotificationRecord(
1440 mTestNotificationChannel, 4, "group2", false);
1441 mService.addNotification(parent);
1442 mService.addNotification(child);
1443 mService.addNotification(child2);
1444 mService.addNotification(newGroup);
1445 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1446 child2.sbn.getKey(), newGroup.sbn.getKey()};
1447 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1448 waitForIdle();
1449 StatusBarNotification[] notifs =
1450 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1451 assertEquals(0, notifs.length);
1452 }
1453
1454 @Test
1455 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1456 final NotificationRecord parent = generateNotificationRecord(
1457 mTestNotificationChannel, 1, "group", true);
1458 final NotificationRecord child = generateNotificationRecord(
1459 mTestNotificationChannel, 2, "group", false);
1460 final NotificationRecord child2 = generateNotificationRecord(
1461 mTestNotificationChannel, 3, "group", false);
1462 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1463 final NotificationRecord newGroup = generateNotificationRecord(
1464 mTestNotificationChannel, 4, "group2", false);
1465 mService.addNotification(parent);
1466 mService.addNotification(child);
1467 mService.addNotification(child2);
1468 mService.addNotification(newGroup);
1469 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1470 parent.getUserId());
1471 waitForIdle();
1472 StatusBarNotification[] notifs =
1473 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1474 assertEquals(1, notifs.length);
1475 }
1476
1477 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001478 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001479 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001480 mService.setPreferencesHelper(mPreferencesHelper);
1481 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001482 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001483 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001484
Julia Reynoldsbad42972017-04-25 13:52:49 -04001485 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001486 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001487 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001488 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001489 anyString(), anyInt(), eq("foo"), anyBoolean());
1490 }
1491
1492 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001493 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001494 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001495 mService.setPreferencesHelper(mPreferencesHelper);
1496 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001497 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001498 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001499
Julia Reynoldsbad42972017-04-25 13:52:49 -04001500 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001501 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001502 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001503 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001504 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001505 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001506
1507 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001508 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001509 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001510
1511 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1512 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1513 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1514
1515 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1516 captor.getValue().getAction());
1517 assertEquals(PKG, captor.getValue().getPackage());
1518 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1519 }
1520
1521 @Test
1522 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001523 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001524
1525 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1526 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1527 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1528
1529 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1530 captor.getValue().getAction());
1531 assertEquals(PKG, captor.getValue().getPackage());
1532 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1533 }
1534
1535 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001536 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001537 mService.setPreferencesHelper(mPreferencesHelper);
1538 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001539 eq(mTestNotificationChannel.getId()), anyBoolean()))
1540 .thenReturn(mTestNotificationChannel);
1541
1542 NotificationChannel updatedChannel =
1543 new NotificationChannel(mTestNotificationChannel.getId(),
1544 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1545
1546 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1547 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1548 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1549
1550 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1551 captor.getValue().getAction());
1552 assertEquals(PKG, captor.getValue().getPackage());
1553 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001554 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001555 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1556 }
1557
1558 @Test
1559 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1560 NotificationChannel existingChannel =
1561 new NotificationChannel(mTestNotificationChannel.getId(),
1562 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001563 mService.setPreferencesHelper(mPreferencesHelper);
1564 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001565 eq(mTestNotificationChannel.getId()), anyBoolean()))
1566 .thenReturn(existingChannel);
1567
1568 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1569 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1570 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1571
1572 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1573 captor.getValue().getAction());
1574 assertEquals(PKG, captor.getValue().getPackage());
1575 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001576 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001577 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1578 }
1579
1580 @Test
1581 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1582 NotificationChannel existingChannel =
1583 new NotificationChannel(mTestNotificationChannel.getId(),
1584 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001585 mService.setPreferencesHelper(mPreferencesHelper);
1586 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001587 eq(mTestNotificationChannel.getId()), anyBoolean()))
1588 .thenReturn(existingChannel);
1589
1590 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1591 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1592 }
1593
1594 @Test
1595 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1596 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001597 mService.setPreferencesHelper(mPreferencesHelper);
1598 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001599 .thenReturn(existing);
1600
1601 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1602 updated.setBlocked(true);
1603
1604 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1605 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1606 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1607
1608 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1609 captor.getValue().getAction());
1610 assertEquals(PKG, captor.getValue().getPackage());
1611 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001612 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001613 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1614 }
1615
1616 @Test
1617 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1618 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1619 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001620 mService.setPreferencesHelper(mPreferencesHelper);
1621 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001622 .thenReturn(existing);
1623
1624 mBinderService.updateNotificationChannelGroupForPackage(
1625 PKG, 0, new NotificationChannelGroup("id", "name"));
1626 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1627 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1628
1629 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1630 captor.getValue().getAction());
1631 assertEquals(PKG, captor.getValue().getPackage());
1632 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001633 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001634 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1635 }
1636
1637 @Test
1638 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1639 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001640 mService.setPreferencesHelper(mPreferencesHelper);
1641 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001642 .thenReturn(existing);
1643
1644 mBinderService.updateNotificationChannelGroupForPackage(
1645 PKG, 0, new NotificationChannelGroup("id", "new name"));
1646 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1647 }
1648
1649 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001650 public void testCreateChannelNotifyListener() throws Exception {
1651 List<String> associations = new ArrayList<>();
1652 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001653 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001654 mService.setPreferencesHelper(mPreferencesHelper);
1655 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001656 eq(mTestNotificationChannel.getId()), anyBoolean()))
1657 .thenReturn(mTestNotificationChannel);
1658 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001659 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001660 eq(channel2.getId()), anyBoolean()))
1661 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001662 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1663 eq(channel2), anyBoolean(), anyBoolean()))
1664 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001665
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001666 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001667 mBinderService.createNotificationChannels(PKG,
1668 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001669 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001670 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001671 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001672 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001673 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001674 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1675 }
1676
1677 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001678 public void testCreateChannelGroupNotifyListener() throws Exception {
1679 List<String> associations = new ArrayList<>();
1680 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001681 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001682 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001683 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1684 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1685
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001686 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001687 mBinderService.createNotificationChannelGroups(PKG,
1688 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001689 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001690 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001691 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001692 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001693 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001694 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1695 }
1696
1697 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001698 public void testUpdateChannelNotifyListener() throws Exception {
1699 List<String> associations = new ArrayList<>();
1700 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001701 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001702 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001703 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001704 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001705 eq(mTestNotificationChannel.getId()), anyBoolean()))
1706 .thenReturn(mTestNotificationChannel);
1707
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001708 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001709 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001710 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001711 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001712 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1713 }
1714
1715 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001716 public void testDeleteChannelNotifyListener() throws Exception {
1717 List<String> associations = new ArrayList<>();
1718 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001719 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001720 mService.setPreferencesHelper(mPreferencesHelper);
1721 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001722 eq(mTestNotificationChannel.getId()), anyBoolean()))
1723 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001724 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001725 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001726 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001727 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001728 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1729 }
1730
1731 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001732 public void testDeleteChannelGroupNotifyListener() throws Exception {
1733 List<String> associations = new ArrayList<>();
1734 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001735 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001736 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001737 mService.setPreferencesHelper(mPreferencesHelper);
1738 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001739 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001740 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001741 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001742 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001743 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001744 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1745 }
1746
1747 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001748 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001749 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001750 List<String> associations = new ArrayList<>();
1751 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001752 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001753 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001754 eq(mTestNotificationChannel.getId()), anyBoolean()))
1755 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001756
1757 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001758 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001759
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001760 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001761 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001762
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001763 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001764 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001765 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1766 }
1767
1768 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001769 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001770 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001771 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001772 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001773
1774 try {
1775 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001776 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001777 fail("listeners that don't have a companion device shouldn't be able to call this");
1778 } catch (SecurityException e) {
1779 // pass
1780 }
1781
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001782 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001783 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001784
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001785 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001786 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1787 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1788 }
1789
1790 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001791 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001792 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001793 List<String> associations = new ArrayList<>();
1794 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001795 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001796 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04001797 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001798 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001799 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001800
1801 try {
1802 mBinderService.updateNotificationChannelFromPrivilegedListener(
1803 null, PKG, UserHandle.ALL, mTestNotificationChannel);
1804 fail("incorrectly allowed a change to a user listener cannot see");
1805 } catch (SecurityException e) {
1806 // pass
1807 }
1808
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001809 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001810 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001811
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001812 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001813 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001814 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1815 }
1816
1817 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001818 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001819 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001820 List<String> associations = new ArrayList<>();
1821 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001822 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001823
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001824 mBinderService.getNotificationChannelsFromPrivilegedListener(
1825 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001826
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001827 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001828 anyString(), anyInt(), anyBoolean());
1829 }
1830
1831 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001832 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001833 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001834 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001835 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001836
1837 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001838 mBinderService.getNotificationChannelsFromPrivilegedListener(
1839 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001840 fail("listeners that don't have a companion device shouldn't be able to call this");
1841 } catch (SecurityException e) {
1842 // pass
1843 }
1844
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001845 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001846 anyString(), anyInt(), anyBoolean());
1847 }
1848
1849 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001850 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
1851 throws Exception {
1852 mService.setPreferencesHelper(mPreferencesHelper);
1853 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1854 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
1855
1856 mBinderService.getNotificationChannelsFromPrivilegedListener(
1857 null, PKG, Process.myUserHandle());
1858
1859 verify(mPreferencesHelper, times(1)).getNotificationChannels(
1860 anyString(), anyInt(), anyBoolean());
1861 }
1862
1863 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04001864 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
1865 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001866 mService.setPreferencesHelper(mPreferencesHelper);
1867 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1868 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
1869
1870 try {
1871 mBinderService.getNotificationChannelsFromPrivilegedListener(
1872 null, PKG, Process.myUserHandle());
1873 fail("listeners that don't have a companion device shouldn't be able to call this");
1874 } catch (SecurityException e) {
1875 // pass
1876 }
1877
1878 verify(mPreferencesHelper, never()).getNotificationChannels(
1879 anyString(), anyInt(), anyBoolean());
1880 }
1881
1882 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001883 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001884 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001885 List<String> associations = new ArrayList<>();
1886 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001887 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001888 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1889 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001890 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001891
1892 try {
1893 mBinderService.getNotificationChannelsFromPrivilegedListener(
1894 null, PKG, Process.myUserHandle());
1895 fail("listener getting channels from a user they cannot see");
1896 } catch (SecurityException e) {
1897 // pass
1898 }
1899
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001900 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001901 anyString(), anyInt(), anyBoolean());
1902 }
1903
1904 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001905 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001906 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001907 List<String> associations = new ArrayList<>();
1908 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001909 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001910
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001911 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1912 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001913
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001914 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001915 }
1916
1917 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001918 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001919 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001920 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001921 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001922
1923 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001924 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1925 null, PKG, Process.myUserHandle());
1926 fail("listeners that don't have a companion device shouldn't be able to call this");
1927 } catch (SecurityException e) {
1928 // pass
1929 }
1930
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001931 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001932 }
1933
1934 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001935 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001936 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001937 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001938 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001939 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1940 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001941 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001942 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001943 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1944 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001945 fail("listeners that don't have a companion device shouldn't be able to call this");
1946 } catch (SecurityException e) {
1947 // pass
1948 }
1949
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001950 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001951 }
Julia Reynoldsda781472017-04-12 09:41:16 -04001952
1953 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04001954 public void testHasCompanionDevice_failure() throws Exception {
1955 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
1956 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04001957 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04001958 }
Julia Reynolds727a7282017-04-13 10:54:01 -04001959
1960 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04001961 public void testHasCompanionDevice_noService() {
1962 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04001963
Julia Reynolds503ed942017-10-04 16:04:56 -04001964 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04001965 }
1966
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001967 @Test
1968 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
1969 final NotificationRecord nonGrouped = generateNotificationRecord(
1970 mTestNotificationChannel, 1, null, false);
1971 final NotificationRecord grouped = generateNotificationRecord(
1972 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001973 mService.addNotification(grouped);
1974 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001975
1976 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04001977 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001978 nonGrouped.getKey(), 100, null);
1979 snoozeNotificationRunnable.run();
1980
1981 // only snooze the one notification
1982 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04001983 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001984 }
1985
1986 @Test
1987 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
1988 final NotificationRecord parent = generateNotificationRecord(
1989 mTestNotificationChannel, 1, "group", true);
1990 final NotificationRecord child = generateNotificationRecord(
1991 mTestNotificationChannel, 2, "group", false);
1992 final NotificationRecord child2 = generateNotificationRecord(
1993 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001994 mService.addNotification(parent);
1995 mService.addNotification(child);
1996 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001997
1998 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04001999 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002000 parent.getKey(), 100, null);
2001 snoozeNotificationRunnable.run();
2002
2003 // snooze parent and children
2004 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2005 }
2006
2007 @Test
2008 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2009 final NotificationRecord parent = generateNotificationRecord(
2010 mTestNotificationChannel, 1, "group", true);
2011 final NotificationRecord child = generateNotificationRecord(
2012 mTestNotificationChannel, 2, "group", false);
2013 final NotificationRecord child2 = generateNotificationRecord(
2014 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002015 mService.addNotification(parent);
2016 mService.addNotification(child);
2017 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002018
2019 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002020 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002021 child2.getKey(), 100, null);
2022 snoozeNotificationRunnable.run();
2023
2024 // only snooze the one child
2025 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2026 }
2027
2028 @Test
2029 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2030 final NotificationRecord parent = generateNotificationRecord(
2031 mTestNotificationChannel, 1, "group", true);
2032 assertTrue(parent.sbn.getNotification().isGroupSummary());
2033 final NotificationRecord child = generateNotificationRecord(
2034 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002035 mService.addNotification(parent);
2036 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002037
2038 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002039 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002040 child.getKey(), 100, null);
2041 snoozeNotificationRunnable.run();
2042
2043 // snooze child and summary
2044 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2045 }
2046
2047 @Test
2048 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2049 final NotificationRecord child = generateNotificationRecord(
2050 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002051 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002052
2053 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002054 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002055 child.getKey(), 100, null);
2056 snoozeNotificationRunnable.run();
2057
2058 // snooze child only
2059 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2060 }
2061
2062 @Test
2063 public void testPostGroupChild_unsnoozeParent() throws Exception {
2064 final NotificationRecord child = generateNotificationRecord(
2065 mTestNotificationChannel, 2, "group", false);
2066
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002067 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002068 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2069 waitForIdle();
2070
2071 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2072 anyString(), anyInt(), eq(child.getGroupKey()));
2073 }
2074
2075 @Test
2076 public void testPostNonGroup_noUnsnoozing() throws Exception {
2077 final NotificationRecord record = generateNotificationRecord(
2078 mTestNotificationChannel, 2, null, false);
2079
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002080 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002081 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2082 waitForIdle();
2083
2084 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2085 }
2086
2087 @Test
2088 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2089 final NotificationRecord parent = generateNotificationRecord(
2090 mTestNotificationChannel, 2, "group", true);
2091
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002092 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002093 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2094 waitForIdle();
2095
2096 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2097 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002098
2099 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002100 public void testSetListenerAccessForUser() throws Exception {
2101 UserHandle user = UserHandle.of(10);
2102 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002103 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2104
Julia Reynolds92febc32017-10-26 11:30:31 -04002105
2106 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2107 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2108 c.flattenToString(), user.getIdentifier(), true, true);
2109 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2110 c.flattenToString(), user.getIdentifier(), false, true);
2111 verify(mAssistants, never()).setPackageOrComponentEnabled(
2112 any(), anyInt(), anyBoolean(), anyBoolean());
2113 }
2114
2115 @Test
2116 public void testSetAssistantAccessForUser() throws Exception {
2117 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002118 List<UserInfo> uis = new ArrayList<>();
2119 UserInfo ui = new UserInfo();
2120 ui.id = 10;
2121 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002122 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002123 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2124
2125 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002126
2127 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2128 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2129 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002130 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002131 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2132 c.flattenToString(), user.getIdentifier(), false, true);
2133 verify(mListeners, never()).setPackageOrComponentEnabled(
2134 any(), anyInt(), anyBoolean(), anyBoolean());
2135 }
2136
2137 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002138 public void testGetAssistantAllowedForUser() throws Exception {
2139 UserHandle user = UserHandle.of(10);
2140 try {
2141 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2142 } catch (IllegalStateException e) {
2143 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2144 throw e;
2145 }
2146 }
2147 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2148 }
2149
2150 @Test
2151 public void testGetAssistantAllowed() throws Exception {
2152 try {
2153 mBinderService.getAllowedNotificationAssistant();
2154 } catch (IllegalStateException e) {
2155 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2156 throw e;
2157 }
2158 }
2159 verify(mAssistants, times(1)).getAllowedComponents(0);
2160 }
2161
2162 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002163 public void testSetDndAccessForUser() throws Exception {
2164 UserHandle user = UserHandle.of(10);
2165 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002166 mBinderService.setNotificationPolicyAccessGrantedForUser(
2167 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002168
2169 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2170 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2171 c.getPackageName(), user.getIdentifier(), true, true);
2172 verify(mAssistants, never()).setPackageOrComponentEnabled(
2173 any(), anyInt(), anyBoolean(), anyBoolean());
2174 verify(mListeners, never()).setPackageOrComponentEnabled(
2175 any(), anyInt(), anyBoolean(), anyBoolean());
2176 }
2177
2178 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002179 public void testSetListenerAccess() throws Exception {
2180 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002181 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002182
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002183 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002184 c.flattenToString(), 0, true, true);
2185 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2186 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002187 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002188 any(), anyInt(), anyBoolean(), anyBoolean());
2189 }
2190
2191 @Test
2192 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002193 List<UserInfo> uis = new ArrayList<>();
2194 UserInfo ui = new UserInfo();
2195 ui.id = 0;
2196 uis.add(ui);
2197 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002198 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002199
2200 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002201
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002202 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002203 c.flattenToString(), 0, true, true);
2204 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2205 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002206 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002207 any(), anyInt(), anyBoolean(), anyBoolean());
2208 }
2209
2210 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002211 public void testSetAssistantAccess_multiProfile() throws Exception {
2212 List<UserInfo> uis = new ArrayList<>();
2213 UserInfo ui = new UserInfo();
2214 ui.id = 0;
2215 uis.add(ui);
2216 UserInfo ui10 = new UserInfo();
2217 ui10.id = 10;
2218 uis.add(ui10);
2219 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2220 ComponentName c = ComponentName.unflattenFromString("package/Component");
2221
2222 mBinderService.setNotificationAssistantAccessGranted(c, true);
2223
2224 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2225 c.flattenToString(), 0, true, true);
2226 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2227 c.flattenToString(), 10, true, true);
2228 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2229 c.flattenToString(), 0, false, true);
2230 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2231 c.flattenToString(), 10, false, true);
2232 verify(mListeners, never()).setPackageOrComponentEnabled(
2233 any(), anyInt(), anyBoolean(), anyBoolean());
2234 }
2235
2236 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002237 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2238 ArrayList<ComponentName> componentList = new ArrayList<>();
2239 ComponentName c = ComponentName.unflattenFromString("package/Component");
2240 componentList.add(c);
2241 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002242 List<UserInfo> uis = new ArrayList<>();
2243 UserInfo ui = new UserInfo();
2244 ui.id = 0;
2245 uis.add(ui);
2246 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002247
Julia Reynolds4afe2642019-05-01 08:42:24 -04002248 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002249
2250 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2251 c.flattenToString(), 0, true, false);
2252 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2253 c.flattenToString(), 0, false, false);
2254 verify(mListeners, never()).setPackageOrComponentEnabled(
2255 any(), anyInt(), anyBoolean(), anyBoolean());
2256 }
2257
2258 @Test
2259 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002260 List<UserInfo> uis = new ArrayList<>();
2261 UserInfo ui = new UserInfo();
2262 ui.id = 10;
2263 uis.add(ui);
2264 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002265 ArrayList<ComponentName> componentList = new ArrayList<>();
2266 ComponentName c = ComponentName.unflattenFromString("package/Component");
2267 componentList.add(c);
2268 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002269 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002270
Julia Reynolds4afe2642019-05-01 08:42:24 -04002271 mBinderService.setNotificationAssistantAccessGrantedForUser(
2272 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002273
2274 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2275 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002276 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002277 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2278 c.flattenToString(), user.getIdentifier(), false, false);
2279 verify(mListeners, never()).setPackageOrComponentEnabled(
2280 any(), anyInt(), anyBoolean(), anyBoolean());
2281 }
2282
2283 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002284 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2285 throws Exception {
2286 List<UserInfo> uis = new ArrayList<>();
2287 UserInfo ui = new UserInfo();
2288 ui.id = 0;
2289 uis.add(ui);
2290 UserInfo ui10 = new UserInfo();
2291 ui10.id = 10;
2292 uis.add(ui10);
2293 UserHandle user = ui.getUserHandle();
2294 ArrayList<ComponentName> componentList = new ArrayList<>();
2295 ComponentName c = ComponentName.unflattenFromString("package/Component");
2296 componentList.add(c);
2297 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2298 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2299
2300 mBinderService.setNotificationAssistantAccessGrantedForUser(
2301 null, user.getIdentifier(), true);
2302
2303 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2304 c.flattenToString(), user.getIdentifier(), true, false);
2305 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2306 c.flattenToString(), ui10.id, true, false);
2307 verify(mAssistants).setUserSet(0, true);
2308 verify(mAssistants).setUserSet(10, true);
2309 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2310 c.flattenToString(), user.getIdentifier(), false, false);
2311 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2312 c.flattenToString(), ui10.id, false, false);
2313 verify(mListeners, never()).setPackageOrComponentEnabled(
2314 any(), anyInt(), anyBoolean(), anyBoolean());
2315 }
2316
2317 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002318 public void testSetDndAccess() throws Exception {
2319 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002320
2321 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002322
2323 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2324 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002325 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002326 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002327 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002328 any(), anyInt(), anyBoolean(), anyBoolean());
2329 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002330
2331 @Test
2332 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2333 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2334 ComponentName c = ComponentName.unflattenFromString("package/Component");
2335 mBinderService.setNotificationListenerAccessGranted(c, true);
2336
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002337 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002338 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002339 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002340 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002341 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002342 any(), anyInt(), anyBoolean(), anyBoolean());
2343 }
2344
2345 @Test
2346 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2347 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2348 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002349 List<UserInfo> uis = new ArrayList<>();
2350 UserInfo ui = new UserInfo();
2351 ui.id = 0;
2352 uis.add(ui);
2353 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2354
Julia Reynolds68263d12017-06-21 14:21:19 -04002355 mBinderService.setNotificationAssistantAccessGranted(c, true);
2356
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002357 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002358 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002359 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002360 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002361 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002362 any(), anyInt(), anyBoolean(), anyBoolean());
2363 }
2364
2365 @Test
2366 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2367 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2368 ComponentName c = ComponentName.unflattenFromString("package/Component");
2369 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2370
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002371 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002372 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002373 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002374 anyString(), anyInt(), anyBoolean(), anyBoolean());
2375 verify(mAssistants, never()).setPackageOrComponentEnabled(
2376 any(), anyInt(), anyBoolean(), anyBoolean());
2377 }
2378
2379 @Test
2380 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2381 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2382 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2383 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002384
2385 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002386
2387 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2388 c.flattenToString(), 0, true, true);
2389 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002390 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002391 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002392 any(), anyInt(), anyBoolean(), anyBoolean());
2393 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002394
2395 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002396 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2397 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2398 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2399 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002400 List<UserInfo> uis = new ArrayList<>();
2401 UserInfo ui = new UserInfo();
2402 ui.id = 0;
2403 uis.add(ui);
2404 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2405
2406 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002407
2408 verify(mListeners, never()).setPackageOrComponentEnabled(
2409 anyString(), anyInt(), anyBoolean(), anyBoolean());
2410 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2411 c.flattenToString(), 0, false, true);
2412 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2413 c.flattenToString(), 0, true, true);
2414 }
2415
2416 @Test
2417 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2418 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2419 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2420 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002421
2422 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002423
2424 verify(mListeners, never()).setPackageOrComponentEnabled(
2425 anyString(), anyInt(), anyBoolean(), anyBoolean());
2426 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2427 c.getPackageName(), 0, true, true);
2428 verify(mAssistants, never()).setPackageOrComponentEnabled(
2429 any(), anyInt(), anyBoolean(), anyBoolean());
2430 }
2431
2432 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002433 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2434 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002435 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002436 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002437 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002438 runnable.run();
2439 waitForIdle();
2440
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002441 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002442 }
2443
2444 @Test
2445 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2446 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002447 NotificationRecord r =
2448 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002449 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002450
2451 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002452 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002453 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002454 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002455 runnable.run();
2456 waitForIdle();
2457
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002458 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002459 }
2460
2461 @Test
2462 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2463 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002464 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2465 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002466 mService.addNotification(r);
2467 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002468
2469 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002470 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002471 runnable.run();
2472 waitForIdle();
2473
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002474 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002475 }
Beverly40239d92017-07-07 10:20:41 -04002476
Julia Reynolds4db59552017-06-30 13:34:01 -04002477 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002478 public void testDontAutogroupIfCritical() throws Exception {
2479 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2480 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2481 mService.addEnqueuedNotification(r);
2482 NotificationManagerService.PostNotificationRunnable runnable =
2483 mService.new PostNotificationRunnable(r.getKey());
2484 runnable.run();
2485
2486 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2487 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2488 runnable = mService.new PostNotificationRunnable(r.getKey());
2489 mService.addEnqueuedNotification(r);
2490
2491 runnable.run();
2492 waitForIdle();
2493
2494 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2495 }
2496
2497 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002498 public void testNoFakeColorizedPermission() throws Exception {
2499 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2500 Notification.Builder nb = new Notification.Builder(mContext,
2501 mTestNotificationChannel.getId())
2502 .setContentTitle("foo")
2503 .setColorized(true)
2504 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2505 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002506 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
2507 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002508 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2509
2510 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2511 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2512 waitForIdle();
2513
Julia Reynolds503ed942017-10-04 16:04:56 -04002514 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds4db59552017-06-30 13:34:01 -04002515 PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
2516
2517 assertFalse(posted.getNotification().isColorized());
2518 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002519
2520 @Test
2521 public void testGetNotificationCountLocked() throws Exception {
2522 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002523 NotificationRecord r =
2524 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002525 mService.addEnqueuedNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002526 }
2527 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002528 NotificationRecord r =
2529 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002530 mService.addNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002531 }
2532
2533 // another package
2534 Notification n =
2535 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2536 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2537 .build();
2538
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002539 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2540 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002541 NotificationRecord otherPackage =
2542 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002543 mService.addEnqueuedNotification(otherPackage);
2544 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002545
2546 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002547 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002548 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002549 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002550 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002551 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002552 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002553 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002554
2555 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002556 assertEquals(39,
Julia Reynolds503ed942017-10-04 16:04:56 -04002557 mService.getNotificationCountLocked(PKG, userId, 0, "tag"));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002558 }
2559
2560 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002561 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002562 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002563 mService.setRankingHandler(rh);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002564
2565 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002566 mService.addNotification(r);
2567 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002568
2569 verify(rh, times(1)).requestSort();
2570 }
2571
2572 @Test
2573 public void testRemoveAutogroup_requestsSort() throws Exception {
2574 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002575 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002576
2577 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2578 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002579 mService.addNotification(r);
2580 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002581
Julia Reynolds51710712017-07-19 13:48:07 -04002582 verify(rh, times(1)).requestSort();
2583 }
2584
2585 @Test
2586 public void testReaddAutogroup_noSort() throws Exception {
2587 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002588 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002589
2590 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2591 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002592 mService.addNotification(r);
2593 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002594
2595 verify(rh, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002596 }
2597
2598 @Test
2599 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002600 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002601 NotificationManagerService.WorkerHandler handler = mock(
2602 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002603 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002604
2605 Map<String, Answer> answers = getSignalExtractorSideEffects();
2606 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002607 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002608 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002609 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002610
2611 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2612
Julia Reynolds503ed942017-10-04 16:04:56 -04002613 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002614 }
2615 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2616 }
2617
2618 @Test
2619 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002620 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002621 NotificationManagerService.WorkerHandler handler = mock(
2622 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002623 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002624
2625 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002626 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002627
Julia Reynolds503ed942017-10-04 16:04:56 -04002628 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002629 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002630 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002631
2632 @Test
2633 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002634 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002635 + "<ranking></ranking>"
2636 + "<enabled_listeners>"
2637 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2638 + "</enabled_listeners>"
2639 + "<enabled_assistants>"
2640 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2641 + "</enabled_assistants>"
2642 + "<dnd_apps>"
2643 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2644 + "</dnd_apps>"
2645 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002646 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002647 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2648 false,
2649 UserHandle.USER_ALL);
2650 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2651 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2652 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002653
2654 // numbers are inflated for setup
2655 verify(mListeners, times(1)).migrateToXml();
2656 verify(mConditionProviders, times(1)).migrateToXml();
2657 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002658 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002659 }
2660
2661 @Test
2662 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2663 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002664 + "<ranking></ranking>"
2665 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002666 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002667 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2668 false,
2669 UserHandle.USER_ALL);
2670 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2671 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2672 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002673
2674 // numbers are inflated for setup
2675 verify(mListeners, times(2)).migrateToXml();
2676 verify(mConditionProviders, times(2)).migrateToXml();
2677 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002678 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002679 }
2680
Annie Meng8b646fd2019-02-01 18:46:42 +00002681 @Test
2682 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2683 final String policyXml = "<notification-policy version=\"1\">"
2684 + "<ranking></ranking>"
2685 + "<enabled_listeners>"
2686 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2687 + "</enabled_listeners>"
2688 + "<enabled_assistants>"
2689 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2690 + "</enabled_assistants>"
2691 + "<dnd_apps>"
2692 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2693 + "</dnd_apps>"
2694 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002695 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00002696 mService.readPolicyXml(
2697 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2698 true,
2699 10);
2700 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2701 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2702 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2703 }
2704
2705 @Test
2706 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2707 final String policyXml = "<notification-policy version=\"1\">"
2708 + "<ranking></ranking>"
2709 + "<enabled_listeners>"
2710 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2711 + "</enabled_listeners>"
2712 + "<enabled_assistants>"
2713 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2714 + "</enabled_assistants>"
2715 + "<dnd_apps>"
2716 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2717 + "</dnd_apps>"
2718 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002719 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00002720 mService.readPolicyXml(
2721 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2722 true,
2723 10);
2724 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
2725 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
2726 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
2727 }
Beverlyd4f96492017-08-02 13:36:11 -04002728
2729 @Test
2730 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
2731 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002732 mService.mZenModeHelper = mZenModeHelper;
2733 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04002734 new Intent(Intent.ACTION_LOCALE_CHANGED));
2735
2736 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
2737 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002738
2739 @Test
2740 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06002741 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002742 final ApplicationInfo legacy = new ApplicationInfo();
2743 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
2744 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
2745 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002746 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
2747 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002748 getContext().setMockPackageManager(mPackageManagerClient);
2749
2750 Notification.Builder nb = new Notification.Builder(mContext,
2751 NotificationChannel.DEFAULT_CHANNEL_ID)
2752 .setContentTitle("foo")
2753 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002754 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002755 .setPriority(Notification.PRIORITY_MIN);
2756
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002757 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
2758 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002759
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002760 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
2761 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002762 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002763
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002764 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002765 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002766
2767 nb = new Notification.Builder(mContext)
2768 .setContentTitle("foo")
2769 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002770 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002771 .setPriority(Notification.PRIORITY_MIN);
2772
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002773 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
2774 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002775
2776 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
2777 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2778 waitForIdle();
2779 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002780 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002781
2782 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04002783 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002784 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
2785 }
Julia Reynolds503ed942017-10-04 16:04:56 -04002786
2787 @Test
2788 public void testStats_updatedOnDirectReply() throws Exception {
2789 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2790 mService.addNotification(r);
2791
2792 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
2793 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00002794 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04002795 }
2796
2797 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002798 public void testStats_updatedOnUserExpansion() throws Exception {
2799 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002800 mService.addNotification(r);
2801
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002802 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
2803 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002804 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002805 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002806
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002807 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
2808 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002809 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002810 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2811 }
2812
2813 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002814 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
2815 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2816 mService.addNotification(r);
2817
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002818 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
2819 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002820 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002821 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
2822
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002823 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
2824 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002825 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002826 verify(mAssistants).notifyAssistantExpansionChangedLocked(
2827 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002828 }
2829
2830 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04002831 public void testStats_updatedOnViewSettings() throws Exception {
2832 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2833 mService.addNotification(r);
2834
2835 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
2836 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
2837 }
2838
2839 @Test
2840 public void testStats_updatedOnVisibilityChanged() throws Exception {
2841 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2842 mService.addNotification(r);
2843
Dieter Hsud39f0d52018-04-14 02:08:30 +08002844 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002845 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2846 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
2847 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2848 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2849 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
2850 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2851 }
2852
2853 @Test
2854 public void testStats_dismissalSurface() throws Exception {
2855 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2856 mService.addNotification(r);
2857
Dieter Hsud39f0d52018-04-14 02:08:30 +08002858 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002859 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002860 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2861 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04002862 waitForIdle();
2863
2864 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
2865 }
2866
2867 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002868 public void testStats_dismissalSentiment() throws Exception {
2869 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2870 mService.addNotification(r);
2871
2872 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2873 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2874 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2875 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
2876 waitForIdle();
2877
2878 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
2879 r.getStats().getDismissalSentiment());
2880 }
2881
2882 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002883 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002884 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2885 mService.addNotification(r);
2886 NotificationManagerService.WorkerHandler handler = mock(
2887 NotificationManagerService.WorkerHandler.class);
2888 mService.setHandler(handler);
2889
Julia Reynolds70aaea72018-07-13 13:38:34 -04002890 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2891
Julia Reynolds503ed942017-10-04 16:04:56 -04002892 Bundle signals = new Bundle();
2893 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04002894 USER_SENTIMENT_NEGATIVE);
2895 Adjustment adjustment = new Adjustment(
2896 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2897 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2898
2899 waitForIdle();
2900
2901 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2902 }
2903
2904 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05002905 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002906 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2907 mService.addNotification(r);
2908 NotificationManagerService.WorkerHandler handler = mock(
2909 NotificationManagerService.WorkerHandler.class);
2910 mService.setHandler(handler);
2911
2912 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04002913 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002914 Adjustment adjustment = new Adjustment(
2915 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2916 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
2917 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2918
2919 waitForIdle();
2920
2921 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2922 verify(handler, times(1)).scheduleCancelNotification(any());
2923 }
2924
2925 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002926 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
2927 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2928 mService.addEnqueuedNotification(r);
2929 NotificationManagerService.WorkerHandler handler = mock(
2930 NotificationManagerService.WorkerHandler.class);
2931 mService.setHandler(handler);
2932 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
2933
2934 Bundle signals = new Bundle();
2935 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2936 USER_SENTIMENT_NEGATIVE);
2937 Adjustment adjustment = new Adjustment(
2938 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2939 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
2940
2941 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
2942 }
2943
2944 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04002945 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05002946 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2947 mService.addEnqueuedNotification(r);
2948 NotificationManagerService.WorkerHandler handler = mock(
2949 NotificationManagerService.WorkerHandler.class);
2950 mService.setHandler(handler);
2951 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
2952
2953 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04002954 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002955 Adjustment adjustment = new Adjustment(
2956 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2957 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
2958
2959 assertEquals(IMPORTANCE_LOW, r.getImportance());
2960 }
2961
2962 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002963 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
2964 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2965 mService.addEnqueuedNotification(r);
2966 NotificationManagerService.WorkerHandler handler = mock(
2967 NotificationManagerService.WorkerHandler.class);
2968 mService.setHandler(handler);
2969 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2970
2971 Bundle signals = new Bundle();
2972 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2973 USER_SENTIMENT_NEGATIVE);
2974 Adjustment adjustment = new Adjustment(
2975 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2976 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
2977
2978 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
2979
2980 waitForIdle();
2981
2982 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2983 }
2984
2985 @Test
2986 public void testUserSentimentChangeTriggersUpdate() throws Exception {
2987 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2988 mService.addNotification(r);
2989 NotificationManagerService.WorkerHandler handler = mock(
2990 NotificationManagerService.WorkerHandler.class);
2991 mService.setHandler(handler);
2992 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
2993
2994 Bundle signals = new Bundle();
2995 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2996 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04002997 Adjustment adjustment = new Adjustment(
2998 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2999 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3000
3001 waitForIdle();
3002
3003 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3004 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003005
3006 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003007 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3008 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3009 mService.addNotification(r);
3010 NotificationManagerService.WorkerHandler handler = mock(
3011 NotificationManagerService.WorkerHandler.class);
3012 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003013 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003014
3015 Bundle signals = new Bundle();
3016 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003017 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003018 Adjustment adjustment = new Adjustment(
3019 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3020 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3021
3022 waitForIdle();
3023
3024 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3025 }
3026
3027 @Test
3028 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3029 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3030 mService.addEnqueuedNotification(r);
3031 NotificationManagerService.WorkerHandler handler = mock(
3032 NotificationManagerService.WorkerHandler.class);
3033 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003034 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003035
3036 Bundle signals = new Bundle();
3037 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003038 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003039 Adjustment adjustment = new Adjustment(
3040 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3041 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3042
Julia Reynolds70aaea72018-07-13 13:38:34 -04003043 assertEquals(USER_SENTIMENT_NEGATIVE,
Julia Reynolds666ccf02018-06-18 10:19:20 -04003044 r.getUserSentiment());
3045 }
3046
3047 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003048 public void testRestore() throws Exception {
3049 int systemChecks = mService.countSystemChecks;
3050 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
3051 assertEquals(1, mService.countSystemChecks - systemChecks);
3052 }
3053
3054 @Test
3055 public void testBackup() throws Exception {
3056 int systemChecks = mService.countSystemChecks;
3057 mBinderService.getBackupPayload(1);
3058 assertEquals(1, mService.countSystemChecks - systemChecks);
3059 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003060
3061 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003062 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003063 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003064 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003065 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3066 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003067 message1.setData("",
3068 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003069 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003070 message2.setData("",
3071 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003072
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003073 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003074 .setContentTitle("foo")
3075 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3076 .setStyle(new Notification.MessagingStyle("")
3077 .addMessage(message1)
3078 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003079 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3080 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003081
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003082 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003083 reset(mUgm);
3084 reset(mUgmInternal);
3085 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003086 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
3087 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003088 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003089 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003090 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003091 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3092
3093 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003094 .setContentTitle("foo")
3095 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3096 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003097 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3098 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003099
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003100 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003101 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003102 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
3103 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003104 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3105 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003106
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003107 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003108 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003109 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
3110 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003111 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003112 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003113
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003114 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003115 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003116 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
3117 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003118 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003119 anyInt(), anyInt());
3120 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003121
3122 @Test
Robin Leed107af62018-04-27 13:55:56 +02003123 public void testVisitUris() throws Exception {
3124 final Uri audioContents = Uri.parse("content://com.example/audio");
3125 final Uri backgroundImage = Uri.parse("content://com.example/background");
3126
3127 Bundle extras = new Bundle();
3128 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3129 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3130
3131 Notification n = new Notification.Builder(mContext, "a")
3132 .setContentTitle("notification with uris")
3133 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3134 .addExtras(extras)
3135 .build();
3136
3137 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3138 n.visitUris(visitor);
3139 verify(visitor, times(1)).accept(eq(audioContents));
3140 verify(visitor, times(1)).accept(eq(backgroundImage));
3141 }
3142
3143 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003144 public void testSetNotificationPolicy_preP_setOldFields() {
3145 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3146 mService.mZenModeHelper = mZenModeHelper;
3147 NotificationManager.Policy userPolicy =
3148 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3149 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3150
3151 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3152 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3153
3154 int expected = SUPPRESSED_EFFECT_BADGE
3155 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003156 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3157 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003158 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3159
3160 assertEquals(expected, actual);
3161 }
3162
3163 @Test
3164 public void testSetNotificationPolicy_preP_setNewFields() {
3165 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3166 mService.mZenModeHelper = mZenModeHelper;
3167 NotificationManager.Policy userPolicy =
3168 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3169 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3170
3171 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3172 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3173
3174 int expected = SUPPRESSED_EFFECT_BADGE;
3175 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3176
3177 assertEquals(expected, actual);
3178 }
3179
3180 @Test
3181 public void testSetNotificationPolicy_preP_setOldNewFields() {
3182 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3183 mService.mZenModeHelper = mZenModeHelper;
3184 NotificationManager.Policy userPolicy =
3185 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3186 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3187
3188 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3189 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3190
3191 int expected =
3192 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3193 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3194
3195 assertEquals(expected, actual);
3196 }
3197
3198 @Test
3199 public void testSetNotificationPolicy_P_setOldFields() {
3200 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3201 mService.mZenModeHelper = mZenModeHelper;
3202 NotificationManager.Policy userPolicy =
3203 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3204 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3205
3206 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3207 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3208
3209 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3210 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3211 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3212 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3213
3214 assertEquals(expected, actual);
3215 }
3216
3217 @Test
3218 public void testSetNotificationPolicy_P_setNewFields() {
3219 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3220 mService.mZenModeHelper = mZenModeHelper;
3221 NotificationManager.Policy userPolicy =
3222 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3223 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3224
3225 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3226 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3227 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3228
3229 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3230 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3231 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3232 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3233
3234 assertEquals(expected, actual);
3235 }
3236
3237 @Test
3238 public void testSetNotificationPolicy_P_setOldNewFields() {
3239 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3240 mService.mZenModeHelper = mZenModeHelper;
3241 NotificationManager.Policy userPolicy =
3242 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3243 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3244
3245 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3246 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3247
3248 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3249 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3250
3251 assertEquals(expected, actual);
3252
3253 appPolicy = new NotificationManager.Policy(0, 0, 0,
3254 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3255 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3256
3257 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3258 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3259 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3260
3261 assertEquals(expected, actual);
3262 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003263
3264 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003265 public void testVisualDifference_foreground() {
3266 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3267 .setContentTitle("foo");
3268 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3269 nb1.build(), new UserHandle(mUid), null, 0);
3270 NotificationRecord r1 =
3271 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3272
3273 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3274 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3275 .setContentTitle("bar");
3276 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3277 nb2.build(), new UserHandle(mUid), null, 0);
3278 NotificationRecord r2 =
3279 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3280
3281 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3282 }
3283
3284 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003285 public void testVisualDifference_diffTitle() {
3286 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3287 .setContentTitle("foo");
3288 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3289 nb1.build(), new UserHandle(mUid), null, 0);
3290 NotificationRecord r1 =
3291 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3292
3293 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3294 .setContentTitle("bar");
3295 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3296 nb2.build(), new UserHandle(mUid), null, 0);
3297 NotificationRecord r2 =
3298 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3299
3300 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3301 }
3302
3303 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003304 public void testVisualDifference_inboxStyle() {
3305 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3306 .setStyle(new Notification.InboxStyle()
3307 .addLine("line1").addLine("line2"));
3308 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3309 nb1.build(), new UserHandle(mUid), null, 0);
3310 NotificationRecord r1 =
3311 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3312
3313 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3314 .setStyle(new Notification.InboxStyle()
3315 .addLine("line1").addLine("line2_changed"));
3316 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3317 nb2.build(), new UserHandle(mUid), null, 0);
3318 NotificationRecord r2 =
3319 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3320
3321 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3322
3323 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3324 .setStyle(new Notification.InboxStyle()
3325 .addLine("line1"));
3326 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3327 nb3.build(), new UserHandle(mUid), null, 0);
3328 NotificationRecord r3 =
3329 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3330
3331 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3332
3333 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3334 .setStyle(new Notification.InboxStyle()
3335 .addLine("line1").addLine("line2").addLine("line3"));
3336 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3337 nb4.build(), new UserHandle(mUid), null, 0);
3338 NotificationRecord r4 =
3339 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3340
3341 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3342
3343 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3344 .setContentText("not an inbox");
3345 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3346 nb5.build(), new UserHandle(mUid), null, 0);
3347 NotificationRecord r5 =
3348 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3349
3350 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3351 }
3352
3353 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003354 public void testVisualDifference_diffText() {
3355 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3356 .setContentText("foo");
3357 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3358 nb1.build(), new UserHandle(mUid), null, 0);
3359 NotificationRecord r1 =
3360 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3361
3362 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3363 .setContentText("bar");
3364 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3365 nb2.build(), new UserHandle(mUid), null, 0);
3366 NotificationRecord r2 =
3367 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3368
3369 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3370 }
3371
3372 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003373 public void testVisualDifference_sameText() {
3374 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3375 .setContentText("foo");
3376 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3377 nb1.build(), new UserHandle(mUid), null, 0);
3378 NotificationRecord r1 =
3379 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3380
3381 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3382 .setContentText("foo");
3383 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3384 nb2.build(), new UserHandle(mUid), null, 0);
3385 NotificationRecord r2 =
3386 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3387
3388 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3389 }
3390
3391 @Test
3392 public void testVisualDifference_sameTextButStyled() {
3393 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3394 .setContentText(Html.fromHtml("<b>foo</b>"));
3395 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3396 nb1.build(), new UserHandle(mUid), null, 0);
3397 NotificationRecord r1 =
3398 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3399
3400 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3401 .setContentText(Html.fromHtml("<b>foo</b>"));
3402 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3403 nb2.build(), new UserHandle(mUid), null, 0);
3404 NotificationRecord r2 =
3405 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3406
3407 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3408 }
3409
3410 @Test
3411 public void testVisualDifference_diffTextButStyled() {
3412 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3413 .setContentText(Html.fromHtml("<b>foo</b>"));
3414 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3415 nb1.build(), new UserHandle(mUid), null, 0);
3416 NotificationRecord r1 =
3417 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3418
3419 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3420 .setContentText(Html.fromHtml("<b>bar</b>"));
3421 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3422 nb2.build(), new UserHandle(mUid), null, 0);
3423 NotificationRecord r2 =
3424 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3425
3426 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3427 }
3428
3429 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003430 public void testVisualDifference_diffProgress() {
3431 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3432 .setProgress(100, 90, false);
3433 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3434 nb1.build(), new UserHandle(mUid), null, 0);
3435 NotificationRecord r1 =
3436 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3437
3438 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3439 .setProgress(100, 100, false);
3440 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3441 nb2.build(), new UserHandle(mUid), null, 0);
3442 NotificationRecord r2 =
3443 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3444
3445 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3446 }
3447
3448 @Test
3449 public void testVisualDifference_diffProgressNotDone() {
3450 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3451 .setProgress(100, 90, false);
3452 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3453 nb1.build(), new UserHandle(mUid), null, 0);
3454 NotificationRecord r1 =
3455 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3456
3457 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3458 .setProgress(100, 91, false);
3459 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3460 nb2.build(), new UserHandle(mUid), null, 0);
3461 NotificationRecord r2 =
3462 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3463
3464 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3465 }
Beverly5a20a5e2018-03-06 15:02:44 -05003466
3467 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003468 public void testVisualDifference_sameProgressStillDone() {
3469 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3470 .setProgress(100, 100, false);
3471 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3472 nb1.build(), new UserHandle(mUid), null, 0);
3473 NotificationRecord r1 =
3474 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3475
3476 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3477 .setProgress(100, 100, false);
3478 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3479 nb2.build(), new UserHandle(mUid), null, 0);
3480 NotificationRecord r2 =
3481 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3482
3483 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3484 }
3485
3486 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003487 public void testVisualDifference_summary() {
3488 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3489 .setGroup("bananas")
3490 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3491 .setContentText("foo");
3492 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3493 nb1.build(), new UserHandle(mUid), null, 0);
3494 NotificationRecord r1 =
3495 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3496
3497 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3498 .setGroup("bananas")
3499 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3500 .setContentText("bar");
3501 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3502 nb2.build(), new UserHandle(mUid), null, 0);
3503 NotificationRecord r2 =
3504 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3505
3506 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3507 }
3508
3509 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003510 public void testVisualDifference_summaryNewNotification() {
3511 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3512 .setGroup("bananas")
3513 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3514 .setContentText("bar");
3515 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3516 nb2.build(), new UserHandle(mUid), null, 0);
3517 NotificationRecord r2 =
3518 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3519
3520 assertFalse(mService.isVisuallyInterruptive(null, r2));
3521 }
3522
3523 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003524 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3525 // post 2 notification from this package
3526 final NotificationRecord notif1 = generateNotificationRecord(
3527 mTestNotificationChannel, 1, null, true);
3528 final NotificationRecord notif2 = generateNotificationRecord(
3529 mTestNotificationChannel, 2, null, false);
3530 mService.addNotification(notif1);
3531 mService.addNotification(notif2);
3532
3533 // on broadcast, hide the 2 notifications
3534 mService.simulatePackageSuspendBroadcast(true, PKG);
3535 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3536 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3537 assertEquals(2, captorHide.getValue().size());
3538
3539 // on broadcast, unhide the 2 notifications
3540 mService.simulatePackageSuspendBroadcast(false, PKG);
3541 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3542 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3543 assertEquals(2, captorUnhide.getValue().size());
3544 }
3545
3546 @Test
3547 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3548 // post 2 notification from this package
3549 final NotificationRecord notif1 = generateNotificationRecord(
3550 mTestNotificationChannel, 1, null, true);
3551 final NotificationRecord notif2 = generateNotificationRecord(
3552 mTestNotificationChannel, 2, null, false);
3553 mService.addNotification(notif1);
3554 mService.addNotification(notif2);
3555
3556 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3557 mService.simulatePackageSuspendBroadcast(true, "test_package");
3558 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3559 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3560 assertEquals(0, captor.getValue().size());
3561 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003562
3563 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003564 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3565 // Post 2 notifications from 2 packages
3566 NotificationRecord pkgA = new NotificationRecord(mContext,
3567 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3568 mService.addNotification(pkgA);
3569 NotificationRecord pkgB = new NotificationRecord(mContext,
3570 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3571 mService.addNotification(pkgB);
3572
3573 // on broadcast, hide one of the packages
3574 mService.simulatePackageDistractionBroadcast(
3575 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3576 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3577 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3578 assertEquals(1, captorHide.getValue().size());
3579 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3580
3581 // on broadcast, unhide the package
3582 mService.simulatePackageDistractionBroadcast(
3583 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3584 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3585 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3586 assertEquals(1, captorUnhide.getValue().size());
3587 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3588 }
3589
3590 @Test
3591 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3592 // Post 2 notifications from 2 packages
3593 NotificationRecord pkgA = new NotificationRecord(mContext,
3594 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3595 mService.addNotification(pkgA);
3596 NotificationRecord pkgB = new NotificationRecord(mContext,
3597 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3598 mService.addNotification(pkgB);
3599
3600 // on broadcast, hide one of the packages
3601 mService.simulatePackageDistractionBroadcast(
3602 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3603 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003604
3605 // should be called only once.
3606 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003607 assertEquals(2, captorHide.getValue().size());
3608 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3609 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3610
3611 // on broadcast, unhide the package
3612 mService.simulatePackageDistractionBroadcast(
3613 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3614 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003615
3616 // should be called only once.
3617 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003618 assertEquals(2, captorUnhide.getValue().size());
3619 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3620 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3621 }
3622
3623 @Test
3624 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3625 // post notification from this package
3626 final NotificationRecord notif1 = generateNotificationRecord(
3627 mTestNotificationChannel, 1, null, true);
3628 mService.addNotification(notif1);
3629
3630 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3631 mService.simulatePackageDistractionBroadcast(
3632 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3633 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3634 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3635 assertEquals(0, captor.getValue().size());
3636 }
3637
3638 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003639 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3640 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3641 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3642 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3643 .thenReturn(new String[] {"a", "b", "c"});
3644 when(mContext.getResources()).thenReturn(mResources);
3645
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003646 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003647 }
3648
3649 @Test
3650 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3651 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3652 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3653 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3654 .thenReturn(new String[] {"a", "b", "c"});
3655 when(mContext.getResources()).thenReturn(mResources);
3656
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003657 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003658 }
3659
3660 @Test
3661 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3662 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3663 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3664 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3665 .thenReturn(new String[] {"a", "b", "c"});
3666 when(mContext.getResources()).thenReturn(mResources);
3667
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003668 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003669 }
3670
3671 @Test
3672 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3673 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3674 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3675 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3676 .thenReturn(new String[] {"a", "b", "c"});
3677 when(mContext.getResources()).thenReturn(mResources);
3678
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003679 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003680 }
3681
3682 @Test
3683 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3684 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3685 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3686 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3687 .thenReturn(new String[] {"a", "b", "c"});
3688 when(mContext.getResources()).thenReturn(mResources);
3689
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003690 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003691 }
3692
3693 @Test
3694 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
3695 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3696 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3697 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3698 .thenReturn(new String[] {"a", "b", "c"});
3699 when(mContext.getResources()).thenReturn(mResources);
3700
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003701 assertEquals(true, mService.canUseManagedServices("d", 0, null));
3702 }
3703
3704 @Test
3705 public void testCanUseManagedServices_hasPermission() throws Exception {
3706 when(mPackageManager.checkPermission("perm", "pkg", 0))
3707 .thenReturn(PackageManager.PERMISSION_GRANTED);
3708
3709 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
3710 }
3711
3712 @Test
3713 public void testCanUseManagedServices_noPermission() throws Exception {
3714 when(mPackageManager.checkPermission("perm", "pkg", 0))
3715 .thenReturn(PackageManager.PERMISSION_DENIED);
3716
3717 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
3718 }
3719
3720 @Test
3721 public void testCanUseManagedServices_permDoesNotMatter() {
3722 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003723 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003724
3725 @Test
3726 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
3727 final NotificationRecord r = generateNotificationRecord(
3728 mTestNotificationChannel, 1, null, true);
3729 r.setTextChanged(true);
3730 mService.addNotification(r);
3731
3732 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
3733 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
3734 new NotificationVisibility[]{});
3735
3736 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3737 }
3738
3739 @Test
3740 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
3741 throws RemoteException {
3742 final NotificationRecord r = generateNotificationRecord(
3743 mTestNotificationChannel, 1, null, true);
3744 r.setTextChanged(true);
3745 mService.addNotification(r);
3746
3747 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
3748
3749 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3750 }
3751
3752 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003753 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003754 throws RemoteException {
3755 final NotificationRecord r = generateNotificationRecord(
3756 mTestNotificationChannel, 1, null, true);
3757 r.setInterruptive(true);
3758 mService.addNotification(r);
3759
3760 mService.maybeRecordInterruptionLocked(r);
3761 mService.maybeRecordInterruptionLocked(r);
3762
3763 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
3764 anyString(), anyString(), anyInt());
3765 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003766
3767 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08003768 public void testBubble() throws Exception {
3769 mBinderService.setBubblesAllowed(PKG, mUid, false);
3770 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05003771 }
3772
3773 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08003774 public void testUserApprovedBubblesForPackage() throws Exception {
3775 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3776 mBinderService.setBubblesAllowed(PKG, mUid, true);
3777 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3778 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3779 }
3780
3781 @Test
3782 public void testUserRejectsBubblesForPackage() throws Exception {
3783 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3784 mBinderService.setBubblesAllowed(PKG, mUid, false);
3785 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3786 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3787 }
3788
3789 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003790 public void testIsCallerInstantApp_primaryUser() throws Exception {
3791 ApplicationInfo info = new ApplicationInfo();
3792 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3793 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04003794 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003795
Julia Reynolds268647a2018-10-25 16:54:27 -04003796 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003797
3798 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04003799 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003800 }
3801
3802 @Test
3803 public void testIsCallerInstantApp_secondaryUser() throws Exception {
3804 ApplicationInfo info = new ApplicationInfo();
3805 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3806 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3807 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04003808 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003809
Julia Reynolds268647a2018-10-25 16:54:27 -04003810 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003811 }
3812
3813 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04003814 public void testIsCallerInstantApp_userAllNotification() throws Exception {
3815 ApplicationInfo info = new ApplicationInfo();
3816 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3817 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
3818 .thenReturn(info);
3819 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3820
3821 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
3822
3823 info.privateFlags = 0;
3824 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
3825 }
3826
3827 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003828 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
3829 ApplicationInfo info = new ApplicationInfo();
3830 info.uid = Binder.getCallingUid();
3831 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3832 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3833
3834 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
3835
3836 assertEquals(info.uid, actualUid);
3837 }
3838
3839 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003840 public void testResolveNotificationUid_sameApp() throws Exception {
3841 ApplicationInfo info = new ApplicationInfo();
3842 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04003843 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003844
3845 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
3846
3847 assertEquals(info.uid, actualUid);
3848 }
3849
3850 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003851 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003852 ApplicationInfo info = new ApplicationInfo();
3853 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003854 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003855
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003856 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
3857
3858 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003859 }
3860
3861 @Test
3862 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
3863 ApplicationInfo info = new ApplicationInfo();
3864 info.uid = 1356347;
3865 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
3866
3867 try {
3868 mService.resolveNotificationUid("caller", "caller", 9, 0);
3869 fail("Incorrect uid didn't throw security exception");
3870 } catch (SecurityException e) {
3871 // yay
3872 }
3873 }
3874
3875 @Test
3876 public void testResolveNotificationUid_delegateAllowed() throws Exception {
3877 int expectedUid = 123;
3878
3879 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3880 mService.setPreferencesHelper(mPreferencesHelper);
3881 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
3882 .thenReturn(true);
3883
3884 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
3885 }
3886
3887 @Test
3888 public void testResolveNotificationUid_androidAllowed() throws Exception {
3889 int expectedUid = 123;
3890
3891 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3892 // no delegate
3893
3894 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
3895 }
3896
3897 @Test
3898 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
3899 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
3900 // no delegate
3901
3902 try {
3903 mService.resolveNotificationUid("caller", "target", 9, 0);
3904 fail("Incorrect uid didn't throw security exception");
3905 } catch (SecurityException e) {
3906 // yay
3907 }
3908 }
Julia Reynolds564273f2018-09-13 15:53:11 -04003909
3910 @Test
3911 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
3912 Notification n = new Notification.Builder(mContext, "").build();
3913 n.flags |= FLAG_FOREGROUND_SERVICE;
3914
3915 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3916 n, new UserHandle(mUid), null, 0);
3917 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3918
3919 mService.addEnqueuedNotification(r);
3920
3921 mInternalService.removeForegroundServiceFlagFromNotification(
3922 PKG, r.sbn.getId(), r.sbn.getUserId());
3923
3924 waitForIdle();
3925
3926 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
3927 }
3928
3929 @Test
3930 public void testRemoveForegroundServiceFlagFromNotification_posted() {
3931 Notification n = new Notification.Builder(mContext, "").build();
3932 n.flags |= FLAG_FOREGROUND_SERVICE;
3933
3934 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3935 n, new UserHandle(mUid), null, 0);
3936 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3937
3938 mService.addNotification(r);
3939
3940 mInternalService.removeForegroundServiceFlagFromNotification(
3941 PKG, r.sbn.getId(), r.sbn.getUserId());
3942
3943 waitForIdle();
3944
3945 ArgumentCaptor<NotificationRecord> captor =
3946 ArgumentCaptor.forClass(NotificationRecord.class);
3947 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
3948
3949 assertEquals(0, captor.getValue().getNotification().flags);
3950 }
Beverly58b24532018-10-02 09:08:23 -04003951
3952 @Test
3953 public void testAllowForegroundToasts() throws Exception {
3954 final String testPackage = "testPackageName";
3955 assertEquals(0, mService.mToastQueue.size());
3956 mService.isSystemUid = false;
3957
3958 // package is not suspended
3959 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
3960 .thenReturn(false);
3961
3962 // notifications from this package are blocked by the user
3963 mService.setPreferencesHelper(mPreferencesHelper);
3964 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
3965
3966 // this app is in the foreground
3967 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
3968
3969 // enqueue toast -> toast should still enqueue
3970 ((INotificationManager)mService.mService).enqueueToast(testPackage,
3971 new TestableToastCallback(), 2000, 0);
3972 assertEquals(1, mService.mToastQueue.size());
3973 }
3974
3975 @Test
3976 public void testDisallowToastsFromSuspendedPackages() throws Exception {
3977 final String testPackage = "testPackageName";
3978 assertEquals(0, mService.mToastQueue.size());
3979 mService.isSystemUid = false;
3980
3981 // package is suspended
3982 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
3983 .thenReturn(true);
3984
3985 // notifications from this package are NOT blocked by the user
3986 mService.setPreferencesHelper(mPreferencesHelper);
3987 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
3988
3989 // enqueue toast -> no toasts enqueued
3990 ((INotificationManager)mService.mService).enqueueToast(testPackage,
3991 new TestableToastCallback(), 2000, 0);
3992 assertEquals(0, mService.mToastQueue.size());
3993 }
3994
3995 @Test
3996 public void testDisallowToastsFromBlockedApps() throws Exception {
3997 final String testPackage = "testPackageName";
3998 assertEquals(0, mService.mToastQueue.size());
3999 mService.isSystemUid = false;
4000
4001 // package is not suspended
4002 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4003 .thenReturn(false);
4004
4005 // notifications from this package are blocked by the user
4006 mService.setPreferencesHelper(mPreferencesHelper);
4007 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4008
4009 // this app is NOT in the foreground
4010 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4011
4012 // enqueue toast -> no toasts enqueued
4013 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4014 new TestableToastCallback(), 2000, 0);
4015 assertEquals(0, mService.mToastQueue.size());
4016 }
4017
4018 @Test
4019 public void testAlwaysAllowSystemToasts() throws Exception {
4020 final String testPackage = "testPackageName";
4021 assertEquals(0, mService.mToastQueue.size());
4022 mService.isSystemUid = true;
4023
4024 // package is suspended
4025 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4026 .thenReturn(true);
4027
4028 // notifications from this package ARE blocked by the user
4029 mService.setPreferencesHelper(mPreferencesHelper);
4030 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4031
4032 // this app is NOT in the foreground
4033 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4034
4035 // enqueue toast -> system toast can still be enqueued
4036 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4037 new TestableToastCallback(), 2000, 0);
4038 assertEquals(1, mService.mToastQueue.size());
4039 }
Tony Mak29996702018-11-26 16:23:34 +00004040
4041 @Test
4042 public void testOnNotificationSmartReplySent() {
4043 final int replyIndex = 2;
4044 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004045 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004046 final boolean generatedByAssistant = true;
4047
4048 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004049 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004050 mService.addNotification(r);
4051
4052 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004053 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4054 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004055 verify(mAssistants).notifyAssistantSuggestedReplySent(
4056 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4057 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004058
4059 @Test
4060 public void testOnNotificationActionClick() {
4061 final int actionIndex = 2;
4062 final Notification.Action action =
4063 new Notification.Action.Builder(null, "text", null).build();
4064 final boolean generatedByAssistant = false;
4065
4066 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4067 mService.addNotification(r);
4068
4069 NotificationVisibility notificationVisibility =
4070 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4071 mService.mNotificationDelegate.onNotificationActionClick(
4072 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4073 generatedByAssistant);
4074 verify(mAssistants).notifyAssistantActionClicked(
4075 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4076 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004077
4078 @Test
4079 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4080 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4081 mService.addNotification(r);
4082
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004083 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4084 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004085 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4086 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4087 };
4088 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4089 new NotificationVisibility[0]);
4090
4091 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4092 }
4093
4094 @Test
4095 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4096 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4097 mService.addNotification(r);
4098
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004099 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4100 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004101
4102 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4103 }
4104
4105 @Test
4106 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4107 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4108 mService.addNotification(r);
4109
Julia Reynolds95334132018-12-19 11:15:35 -05004110 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004111 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4112 };
4113 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4114 new NotificationVisibility[0]);
4115
4116 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4117 }
Julia Reynolds95334132018-12-19 11:15:35 -05004118
4119 public void testReportSeen_delegated() {
4120 Notification.Builder nb =
4121 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4122 .setContentTitle("foo")
4123 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4124
4125 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4126 nb.build(), new UserHandle(mUid), null, 0);
4127 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4128
4129 mService.reportSeen(r);
4130 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4131
4132 }
4133
4134 @Test
4135 public void testReportSeen_notDelegated() {
4136 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4137
4138 mService.reportSeen(r);
4139 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4140 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004141
4142 @Test
4143 public void testNotificationStats_notificationError() {
4144 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4145 mService.addNotification(r);
4146
4147 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4148 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4149 new UserHandle(mUid), null, 0);
4150 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4151 mService.addEnqueuedNotification(update);
4152 assertNull(update.sbn.getNotification().getSmallIcon());
4153
4154 NotificationManagerService.PostNotificationRunnable runnable =
4155 mService.new PostNotificationRunnable(update.getKey());
4156 runnable.run();
4157 waitForIdle();
4158
4159 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4160 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4161 assertNotNull(captor.getValue());
4162 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004163
4164 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004165 public void testCanNotifyAsUser_crossUser() throws Exception {
4166 // same user no problem
4167 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4168
4169 // cross user, no permission, problem
4170 try {
4171 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4172 fail("Should not be callable cross user without cross user permission");
4173 } catch (SecurityException e) {
4174 // good
4175 }
4176
4177 // cross user, with permission, no problem
4178 TestablePermissions perms = mContext.getTestablePermissions();
4179 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4180 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4181 }
4182
4183 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004184 public void testgetNotificationChannels_crossUser() throws Exception {
4185 // same user no problem
4186 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4187
4188 // cross user, no permission, problem
4189 try {
4190 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4191 fail("Should not be callable cross user without cross user permission");
4192 } catch (SecurityException e) {
4193 // good
4194 }
4195
4196 // cross user, with permission, no problem
4197 TestablePermissions perms = mContext.getTestablePermissions();
4198 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4199 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4200 }
4201
4202 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004203 public void setDefaultAssistantForUser_fromConfigXml() {
4204 clearDeviceConfig();
4205 ComponentName xmlConfig = new ComponentName("config", "xml");
4206 when(mResources
4207 .getString(
4208 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4209 .thenReturn(xmlConfig.flattenToString());
4210 when(mContext.getResources()).thenReturn(mResources);
4211 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4212 .thenReturn(Collections.singleton(xmlConfig));
4213 mService.setNotificationAssistantAccessGrantedCallback(
4214 mNotificationAssistantAccessGrantedCallback);
4215
4216 mService.setDefaultAssistantForUser(0);
4217
4218 verify(mNotificationAssistantAccessGrantedCallback)
4219 .onGranted(eq(xmlConfig), eq(0), eq(true));
4220 }
4221
4222 @Test
4223 public void setDefaultAssistantForUser_fromDeviceConfig() {
4224 ComponentName xmlConfig = new ComponentName("xml", "config");
4225 ComponentName deviceConfig = new ComponentName("device", "config");
4226 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4227 when(mResources
4228 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4229 .thenReturn(xmlConfig.flattenToString());
4230 when(mContext.getResources()).thenReturn(mResources);
4231 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4232 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
4233 mService.setNotificationAssistantAccessGrantedCallback(
4234 mNotificationAssistantAccessGrantedCallback);
4235
4236 mService.setDefaultAssistantForUser(0);
4237
4238 verify(mNotificationAssistantAccessGrantedCallback)
4239 .onGranted(eq(deviceConfig), eq(0), eq(true));
4240 }
4241
4242 @Test
4243 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4244 ComponentName xmlConfig = new ComponentName("xml", "config");
4245 ComponentName deviceConfig = new ComponentName("device", "config");
4246 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4247 when(mResources
4248 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4249 .thenReturn(xmlConfig.flattenToString());
4250 when(mContext.getResources()).thenReturn(mResources);
4251 // Only xmlConfig is valid, deviceConfig is not.
4252 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4253 .thenReturn(Collections.singleton(xmlConfig));
4254 mService.setNotificationAssistantAccessGrantedCallback(
4255 mNotificationAssistantAccessGrantedCallback);
4256
4257 mService.setDefaultAssistantForUser(0);
4258
4259 verify(mNotificationAssistantAccessGrantedCallback)
4260 .onGranted(eq(xmlConfig), eq(0), eq(true));
4261 }
4262
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004263 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004264 public void testFlagBubble() throws RemoteException {
4265 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004266 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004267
4268 // Notif with bubble metadata but not our other misc requirements
4269 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4270 null /* tvExtender */, true /* isBubble */);
4271
4272 // Say we're foreground
4273 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4274 IMPORTANCE_FOREGROUND);
4275
4276 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4277 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4278 waitForIdle();
4279
4280 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4281 assertEquals(1, notifs.length);
4282 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4283 assertTrue(mService.getNotificationRecord(
4284 nr.sbn.getKey()).getNotification().isBubbleNotification());
4285 }
4286
4287 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004288 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4289 // Bubbles are allowed!
4290 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4291
4292 // Notif with bubble metadata but not our other misc requirements
4293 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4294 null /* tvExtender */, true /* isBubble */);
4295
4296 // Say we're foreground
4297 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4298 IMPORTANCE_FOREGROUND);
4299
4300 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4301 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4302 waitForIdle();
4303
4304 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4305 assertEquals(1, notifs.length);
4306 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4307 assertFalse(mService.getNotificationRecord(
4308 nr.sbn.getKey()).getNotification().isBubbleNotification());
4309 }
4310
4311 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004312 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004313 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004314 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004315
Mady Mellorbe797962019-04-01 16:04:24 -07004316 // Notif with bubble metadata but not our other misc requirements
4317 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4318 null /* tvExtender */, true /* isBubble */);
4319
4320 // Say we're foreground
4321 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4322 IMPORTANCE_FOREGROUND);
4323
4324 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4325 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4326 waitForIdle();
4327
4328 // yes allowed, yes foreground, yes bubble
4329 assertTrue(mService.getNotificationRecord(
4330 nr.sbn.getKey()).getNotification().isBubbleNotification());
4331 }
4332
4333 @Test
4334 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4335 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004336 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004337
4338 // Notif with bubble metadata but not our other misc requirements
4339 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4340 null /* tvExtender */, true /* isBubble */);
4341
4342 // Make sure we're NOT foreground
4343 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4344 IMPORTANCE_VISIBLE);
4345
4346 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4347 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4348 waitForIdle();
4349
4350 // yes allowed but NOT foreground, no bubble
4351 assertFalse(mService.getNotificationRecord(
4352 nr.sbn.getKey()).getNotification().isBubbleNotification());
4353 }
4354
4355 @Test
4356 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4357 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004358 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004359
4360 // Notif with bubble metadata but not our other misc requirements
4361 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4362 null /* tvExtender */, true /* isBubble */);
4363
4364 // Send notif when we're foreground
4365 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4366 IMPORTANCE_FOREGROUND);
4367 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4368 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4369 waitForIdle();
4370
4371 // yes allowed, yes foreground, yes bubble
4372 assertTrue(mService.getNotificationRecord(
4373 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4374
4375 // Send a new update when we're not foreground
4376 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4377 null /* tvExtender */, true /* isBubble */);
4378
4379 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4380 IMPORTANCE_VISIBLE);
4381 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4382 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4383 waitForIdle();
4384
4385 // yes allowed, previously foreground / flagged, yes bubble
4386 assertTrue(mService.getNotificationRecord(
4387 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4388
4389 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4390 assertEquals(1, notifs2.length);
4391 assertEquals(1, mService.getNotificationRecordCount());
4392 }
4393
4394 @Test
4395 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4396 throws RemoteException {
4397 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004398 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004399
4400 // Notif with bubble metadata but not our other misc requirements
4401 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4402 null /* tvExtender */, true /* isBubble */);
4403
4404 // Send notif when we're foreground
4405 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4406 IMPORTANCE_FOREGROUND);
4407 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4408 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4409 waitForIdle();
4410
4411 // yes allowed, yes foreground, yes bubble
4412 assertTrue(mService.getNotificationRecord(
4413 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4414
4415 // Remove the bubble
4416 mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(),
4417 nr1.sbn.getUserId());
4418 waitForIdle();
4419
4420 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4421 assertEquals(0, notifs.length);
4422 assertEquals(0, mService.getNotificationRecordCount());
4423
4424 // Send a new update when we're not foreground
4425 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4426 null /* tvExtender */, true /* isBubble */);
4427
4428 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4429 IMPORTANCE_VISIBLE);
4430 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4431 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4432 waitForIdle();
4433
4434 // yes allowed, but was removed & no foreground, so no bubble
4435 assertFalse(mService.getNotificationRecord(
4436 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4437
4438 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4439 assertEquals(1, notifs2.length);
4440 assertEquals(1, mService.getNotificationRecordCount());
4441 }
4442
4443 @Test
4444 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4445 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004446 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004447
4448 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004449 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004450 // Give it a person
4451 Person person = new Person.Builder()
4452 .setName("bubblebot")
4453 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004454 // It needs remote input to be bubble-able
4455 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4456 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4457 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4458 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4459 inputIntent).addRemoteInput(remoteInput)
4460 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004461 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004462 Notification.Builder nb = new Notification.Builder(mContext,
4463 mTestNotificationChannel.getId())
4464 .setContentTitle("foo")
4465 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004466 .setStyle(new Notification.MessagingStyle(person)
4467 .setConversationTitle("Bubble Chat")
4468 .addMessage("Hello?",
4469 SystemClock.currentThreadTimeMillis() - 300000, person)
4470 .addMessage("Is it me you're looking for?",
4471 SystemClock.currentThreadTimeMillis(), person)
4472 )
Mady Mellora10448e2019-04-26 13:50:58 -07004473 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -07004474 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4475
4476 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4477 nb.build(), new UserHandle(mUid), null, 0);
4478 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4479
4480 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4481 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4482 waitForIdle();
4483
4484 // yes allowed, yes messaging, yes bubble
4485 assertTrue(mService.getNotificationRecord(
4486 sbn.getKey()).getNotification().isBubbleNotification());
4487 }
4488
4489 @Test
4490 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4491 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004492 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004493
4494 // Give it bubble metadata
4495 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4496 // Give it a person
4497 Person person = new Person.Builder()
4498 .setName("bubblebot")
4499 .build();
4500 // Make it a phone call
4501 Notification.Builder nb = new Notification.Builder(mContext,
4502 mTestNotificationChannel.getId())
4503 .setCategory(CATEGORY_CALL)
4504 .addPerson(person)
4505 .setContentTitle("foo")
4506 .setBubbleMetadata(data)
4507 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4508
4509 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4510 nb.build(), new UserHandle(mUid), null, 0);
4511 // Make sure it has foreground service
4512 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4513 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4514
4515 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4516 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4517 waitForIdle();
4518
4519 // yes phone call, yes person, yes foreground service, yes bubble
4520 assertTrue(mService.getNotificationRecord(
4521 sbn.getKey()).getNotification().isBubbleNotification());
4522 }
4523
4524 @Test
4525 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4526 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004527 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004528
4529 // Give it bubble metadata
4530 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4531 // Give it a person
4532 Person person = new Person.Builder()
4533 .setName("bubblebot")
4534 .build();
4535 // Make it a phone call
4536 Notification.Builder nb = new Notification.Builder(mContext,
4537 mTestNotificationChannel.getId())
4538 .setCategory(CATEGORY_CALL)
4539 .addPerson(person)
4540 .setContentTitle("foo")
4541 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004542 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4543
4544 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4545 nb.build(), new UserHandle(mUid), null, 0);
4546 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4547
4548 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4549 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4550 waitForIdle();
4551
Mady Mellorbe797962019-04-01 16:04:24 -07004552 // yes phone call, yes person, NO foreground service, no bubble
4553 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004554 sbn.getKey()).getNotification().isBubbleNotification());
4555 }
4556
4557 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004558 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4559 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004560 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004561
4562 // Give it bubble metadata
4563 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4564 // Make it a phone call
4565 Notification.Builder nb = new Notification.Builder(mContext,
4566 mTestNotificationChannel.getId())
4567 .setCategory(CATEGORY_CALL)
4568 .setContentTitle("foo")
4569 .setBubbleMetadata(data)
4570 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4571
4572 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4573 nb.build(), new UserHandle(mUid), null, 0);
4574 // Make sure it has foreground service
4575 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4576 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4577
4578 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4579 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4580 waitForIdle();
4581
4582 // yes phone call, yes foreground service, BUT NO person, no bubble
4583 assertFalse(mService.getNotificationRecord(
4584 sbn.getKey()).getNotification().isBubbleNotification());
4585 }
4586
4587 @Test
4588 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4589 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004590 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004591
4592 // Give it bubble metadata
4593 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4594 // Give it a person
4595 Person person = new Person.Builder()
4596 .setName("bubblebot")
4597 .build();
4598 // No category
4599 Notification.Builder nb = new Notification.Builder(mContext,
4600 mTestNotificationChannel.getId())
4601 .addPerson(person)
4602 .setContentTitle("foo")
4603 .setBubbleMetadata(data)
4604 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4605
4606 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4607 nb.build(), new UserHandle(mUid), null, 0);
4608 // Make sure it has foreground service
4609 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4610 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4611
4612 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4613 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4614 waitForIdle();
4615
4616 // yes person, yes foreground service, BUT NO call, no bubble
4617 assertFalse(mService.getNotificationRecord(
4618 sbn.getKey()).getNotification().isBubbleNotification());
4619 }
4620
4621 @Test
4622 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004623 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004624 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004625
Mady Mellorbe797962019-04-01 16:04:24 -07004626 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004627 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004628 // Give it a person
4629 Person person = new Person.Builder()
4630 .setName("bubblebot")
4631 .build();
4632 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004633 Notification.Builder nb = new Notification.Builder(mContext,
4634 mTestNotificationChannel.getId())
4635 .setContentTitle("foo")
4636 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004637 .setStyle(new Notification.MessagingStyle(person)
4638 .setConversationTitle("Bubble Chat")
4639 .addMessage("Hello?",
4640 SystemClock.currentThreadTimeMillis() - 300000, person)
4641 .addMessage("Is it me you're looking for?",
4642 SystemClock.currentThreadTimeMillis(), person)
4643 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004644 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4645
4646 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4647 nb.build(), new UserHandle(mUid), null, 0);
4648 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4649
4650 // Post the notification
4651 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4652 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4653 waitForIdle();
4654
4655 // not allowed, no bubble
4656 assertFalse(mService.getNotificationRecord(
4657 sbn.getKey()).getNotification().isBubbleNotification());
4658 }
4659
4660 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004661 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004662 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004663 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004664
4665 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07004666 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004667
4668 // Post the notification
Mady Mellorbe797962019-04-01 16:04:24 -07004669 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004670 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4671 waitForIdle();
4672
4673 // no bubble metadata, no bubble
4674 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07004675 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004676 }
4677
4678 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004679 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004680 // Bubbles are allowed except on this channel
4681 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004682
Mady Mellorbe797962019-04-01 16:04:24 -07004683 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004684 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004685 // Give it a person
4686 Person person = new Person.Builder()
4687 .setName("bubblebot")
4688 .build();
4689 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004690 Notification.Builder nb = new Notification.Builder(mContext,
4691 mTestNotificationChannel.getId())
4692 .setContentTitle("foo")
4693 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004694 .setStyle(new Notification.MessagingStyle(person)
4695 .setConversationTitle("Bubble Chat")
4696 .addMessage("Hello?",
4697 SystemClock.currentThreadTimeMillis() - 300000, person)
4698 .addMessage("Is it me you're looking for?",
4699 SystemClock.currentThreadTimeMillis(), person)
4700 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004701 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4702
4703 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4704 nb.build(), new UserHandle(mUid), null, 0);
4705 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4706
4707 // Post the notification
4708 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4709 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4710 waitForIdle();
4711
4712 // channel not allowed, no bubble
4713 assertFalse(mService.getNotificationRecord(
4714 sbn.getKey()).getNotification().isBubbleNotification());
4715 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004716
Mady Mellor49b1bf12019-03-29 12:00:02 -07004717 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004718 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004719 // Bubbles are not allowed!
4720 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004721
4722 // Give it bubble metadata
4723 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4724 // Give it a person
4725 Person person = new Person.Builder()
4726 .setName("bubblebot")
4727 .build();
4728 // Make it a phone call
4729 Notification.Builder nb = new Notification.Builder(mContext,
4730 mTestNotificationChannel.getId())
4731 .setCategory(CATEGORY_CALL)
4732 .addPerson(person)
4733 .setContentTitle("foo")
4734 .setBubbleMetadata(data)
4735 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4736
4737 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4738 nb.build(), new UserHandle(mUid), null, 0);
4739 // Make sure it has foreground service
4740 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4741 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4742
4743 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4744 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4745 waitForIdle();
4746
4747 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
4748 assertFalse(mService.getNotificationRecord(
4749 sbn.getKey()).getNotification().isBubbleNotification());
4750 }
4751
4752 @Test
4753 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004754 // Bubbles are allowed, but not on channel.
4755 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004756
4757 // Give it bubble metadata
4758 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4759 // Give it a person
4760 Person person = new Person.Builder()
4761 .setName("bubblebot")
4762 .build();
4763 // Make it a phone call
4764 Notification.Builder nb = new Notification.Builder(mContext,
4765 mTestNotificationChannel.getId())
4766 .setCategory(CATEGORY_CALL)
4767 .addPerson(person)
4768 .setContentTitle("foo")
4769 .setBubbleMetadata(data)
4770 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4771
4772 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4773 nb.build(), new UserHandle(mUid), null, 0);
4774 // Make sure it has foreground service
4775 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4776 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4777
4778 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4779 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4780 waitForIdle();
4781
4782 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
4783 assertFalse(mService.getNotificationRecord(
4784 sbn.getKey()).getNotification().isBubbleNotification());
4785 }
4786
4787 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07004788 public void testCancelAllNotifications_cancelsBubble() throws Exception {
4789 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4790 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
4791 mService.addNotification(nr);
4792
4793 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
4794 waitForIdle();
4795
4796 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4797 assertEquals(0, notifs.length);
4798 assertEquals(0, mService.getNotificationRecordCount());
4799 }
4800
4801 @Test
4802 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
4803 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4804 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4805
4806 // Post the notification
4807 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4808 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
4809 waitForIdle();
4810
4811 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4812 assertEquals(1, notifs.length);
4813 assertEquals(1, mService.getNotificationRecordCount());
4814
4815 mBinderService.cancelNotificationWithTag(PKG, null, nrBubble.sbn.getId(),
4816 nrBubble.sbn.getUserId());
4817 waitForIdle();
4818
4819 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4820 assertEquals(0, notifs2.length);
4821 assertEquals(0, mService.getNotificationRecordCount());
4822 }
4823
4824 @Test
4825 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
4826 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4827 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4828 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4829
4830 mService.addNotification(nrNormal);
4831 mService.addNotification(nrBubble);
4832
4833 mService.getBinderService().cancelNotificationsFromListener(null, null);
4834 waitForIdle();
4835
4836 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4837 assertEquals(1, notifs.length);
4838 assertEquals(1, mService.getNotificationRecordCount());
4839 }
4840
4841 @Test
4842 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
4843 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4844 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4845 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4846
4847 mService.addNotification(nrNormal);
4848 mService.addNotification(nrBubble);
4849
4850 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
4851 mService.getBinderService().cancelNotificationsFromListener(null, keys);
4852 waitForIdle();
4853
4854 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4855 assertEquals(1, notifs.length);
4856 assertEquals(1, mService.getNotificationRecordCount());
4857 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004858
Julia Reynolds4214da92019-04-10 15:04:06 -04004859 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04004860 public void testGetAllowedAssistantAdjustments() throws Exception {
4861 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004862 assertNotNull(capabilities);
4863
4864 for (int i = capabilities.size() - 1; i >= 0; i--) {
4865 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04004866 mBinderService.disallowAssistantAdjustment(capability);
4867 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
4868 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004869 assertNotNull(currentCapabilities);
4870 assertFalse(currentCapabilities.contains(capability));
4871 }
4872 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004873
Julia Reynolds4214da92019-04-10 15:04:06 -04004874 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004875 public void testAdjustRestrictedKey() throws Exception {
4876 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04004877 mService.addNotification(r);
4878 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004879
4880 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
4881 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
4882
4883 Bundle signals = new Bundle();
4884 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
4885 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
4886 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
4887 "", r.getUser().getIdentifier());
4888
4889 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
4890 r.applyAdjustments();
4891
4892 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
4893 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
4894 }
Julia Reynolds657d1642019-03-27 12:15:57 -04004895
Julia Reynolds4214da92019-04-10 15:04:06 -04004896 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004897 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04004898 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
4899 .thenReturn(true);
4900 mService.setZenHelper(mock(ZenModeHelper.class));
4901 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004902 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
4903 boolean isEnabled = true;
4904 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4905 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4906
4907 try {
4908 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04004909 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004910 } catch (IllegalArgumentException e) {
4911 // yay
4912 }
4913
4914 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4915 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
4916 mBinderService.addAutomaticZenRule(rule);
4917
4918 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4919 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4920 mBinderService.addAutomaticZenRule(rule);
4921 }
4922
Julia Reynolds4214da92019-04-10 15:04:06 -04004923 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04004924 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
4925 try {
4926 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
4927 mUid + UserHandle.PER_USER_RANGE);
4928 fail("Cannot call cross user without permission");
4929 } catch (SecurityException e) {
4930 // pass
4931 }
4932
4933 // cross user, with permission, no problem
4934 TestablePermissions perms = mContext.getTestablePermissions();
4935 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4936 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
4937 mUid + UserHandle.PER_USER_RANGE);
4938 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04004939
Julia Reynolds4214da92019-04-10 15:04:06 -04004940 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04004941 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
4942 try {
4943 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
4944 mUid + UserHandle.PER_USER_RANGE);
4945 fail("Cannot call cross user without permission");
4946 } catch (SecurityException e) {
4947 // pass
4948 }
4949
4950 // cross user, with permission, no problem
4951 TestablePermissions perms = mContext.getTestablePermissions();
4952 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4953 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
4954 mUid + UserHandle.PER_USER_RANGE);
4955 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07004956
4957 @Test
4958 public void testNotificationBubbleChanged_false() throws Exception {
4959 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004960 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07004961
4962 // Notif with bubble metadata but not our other misc requirements
4963 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4964 null /* tvExtender */, true /* isBubble */);
4965
4966 // Say we're foreground
4967 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4968 IMPORTANCE_FOREGROUND);
4969
4970 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4971 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4972 waitForIdle();
4973
Mady Mellor66efd5e2019-05-15 13:38:11 -07004974 // Reset as this is called when the notif is first sent
4975 reset(mListeners);
4976
Mady Mellora54e9fa2019-04-18 13:26:18 -07004977 // First we were a bubble
4978 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
4979 assertEquals(1, notifsBefore.length);
4980 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
4981
4982 // Notify we're not a bubble
4983 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
4984 waitForIdle();
4985
Mady Mellor3a0a1b42019-05-23 06:40:21 -07004986 // Make sure we are not a bubble
4987 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
4988 assertEquals(1, notifsAfter.length);
4989 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07004990 }
4991
4992 @Test
4993 public void testNotificationBubbleChanged_true() throws Exception {
4994 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004995 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07004996
4997 // Plain notification that has bubble metadata
4998 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4999 null /* tvExtender */, true /* isBubble */);
5000 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5001 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5002 waitForIdle();
5003
5004 // Would be a normal notification because wouldn't have met requirements to bubble
5005 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5006 assertEquals(1, notifsBefore.length);
5007 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5008
5009 // Make the package foreground so that we're allowed to be a bubble
5010 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5011 IMPORTANCE_FOREGROUND);
5012
Mady Mellor66efd5e2019-05-15 13:38:11 -07005013 // Reset as this is called when the notif is first sent
5014 reset(mListeners);
5015
Mady Mellora54e9fa2019-04-18 13:26:18 -07005016 // Notify we are now a bubble
5017 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5018 waitForIdle();
5019
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005020 // Make sure we are a bubble
5021 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5022 assertEquals(1, notifsAfter.length);
5023 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005024 }
5025
5026 @Test
5027 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5028 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005029 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005030
5031 // Notif that is not a bubble
5032 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5033 null /* tvExtender */, true /* isBubble */);
5034 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5035 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5036 waitForIdle();
5037
Mady Mellor66efd5e2019-05-15 13:38:11 -07005038 // Reset as this is called when the notif is first sent
5039 reset(mListeners);
5040
Mady Mellora54e9fa2019-04-18 13:26:18 -07005041 // Would be a normal notification because wouldn't have met requirements to bubble
5042 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5043 assertEquals(1, notifsBefore.length);
5044 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5045
5046 // Notify we are now a bubble
5047 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5048 waitForIdle();
5049
5050 // We still wouldn't be a bubble because the notification didn't meet requirements
5051 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5052 assertEquals(1, notifsAfter.length);
5053 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5054 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005055
5056 @Test
5057 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5058 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005059 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005060
5061 // Plain notification that has bubble metadata
5062 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5063 null /* tvExtender */, true /* isBubble */);
5064 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5065 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5066 waitForIdle();
5067
5068 // Would be a normal notification because wouldn't have met requirements to bubble
5069 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5070 assertEquals(1, notifsBefore.length);
5071 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5072
5073 // Make the package foreground so that we're allowed to be a bubble
5074 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5075 IMPORTANCE_FOREGROUND);
5076
5077 // And we are low ram
5078 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5079
5080 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5081 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5082 assertEquals(1, notifsAfter.length);
5083 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005084 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005085}