blob: b5e4934f49bfd85e04bc6be95e0a7dff66d3948a [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
Julia Reynolds4f5020d2019-06-03 12:48:49 -04001511 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001512 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());
Julia Reynolds4f5020d2019-06-03 12:48:49 -04001518 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1519 }
1520
1521 @Test
1522 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1523 mService.setPreferencesHelper(mPreferencesHelper);
1524
1525 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1526 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001527 }
1528
1529 @Test
1530 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001531 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001532
1533 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1534 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1535 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1536
1537 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1538 captor.getValue().getAction());
1539 assertEquals(PKG, captor.getValue().getPackage());
1540 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1541 }
1542
1543 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001544 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001545 mService.setPreferencesHelper(mPreferencesHelper);
1546 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001547 eq(mTestNotificationChannel.getId()), anyBoolean()))
1548 .thenReturn(mTestNotificationChannel);
1549
1550 NotificationChannel updatedChannel =
1551 new NotificationChannel(mTestNotificationChannel.getId(),
1552 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1553
1554 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1555 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1556 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1557
1558 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1559 captor.getValue().getAction());
1560 assertEquals(PKG, captor.getValue().getPackage());
1561 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001562 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001563 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1564 }
1565
1566 @Test
1567 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1568 NotificationChannel existingChannel =
1569 new NotificationChannel(mTestNotificationChannel.getId(),
1570 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001571 mService.setPreferencesHelper(mPreferencesHelper);
1572 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001573 eq(mTestNotificationChannel.getId()), anyBoolean()))
1574 .thenReturn(existingChannel);
1575
1576 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1577 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1578 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1579
1580 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1581 captor.getValue().getAction());
1582 assertEquals(PKG, captor.getValue().getPackage());
1583 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001584 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001585 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1586 }
1587
1588 @Test
1589 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1590 NotificationChannel existingChannel =
1591 new NotificationChannel(mTestNotificationChannel.getId(),
1592 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001593 mService.setPreferencesHelper(mPreferencesHelper);
1594 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001595 eq(mTestNotificationChannel.getId()), anyBoolean()))
1596 .thenReturn(existingChannel);
1597
1598 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1599 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1600 }
1601
1602 @Test
1603 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1604 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001605 mService.setPreferencesHelper(mPreferencesHelper);
1606 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001607 .thenReturn(existing);
1608
1609 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1610 updated.setBlocked(true);
1611
1612 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1613 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1614 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1615
1616 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1617 captor.getValue().getAction());
1618 assertEquals(PKG, captor.getValue().getPackage());
1619 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001620 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001621 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1622 }
1623
1624 @Test
1625 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1626 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1627 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001628 mService.setPreferencesHelper(mPreferencesHelper);
1629 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001630 .thenReturn(existing);
1631
1632 mBinderService.updateNotificationChannelGroupForPackage(
1633 PKG, 0, new NotificationChannelGroup("id", "name"));
1634 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1635 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1636
1637 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1638 captor.getValue().getAction());
1639 assertEquals(PKG, captor.getValue().getPackage());
1640 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001641 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001642 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1643 }
1644
1645 @Test
1646 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1647 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001648 mService.setPreferencesHelper(mPreferencesHelper);
1649 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001650 .thenReturn(existing);
1651
1652 mBinderService.updateNotificationChannelGroupForPackage(
1653 PKG, 0, new NotificationChannelGroup("id", "new name"));
1654 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1655 }
1656
1657 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001658 public void testCreateChannelNotifyListener() throws Exception {
1659 List<String> associations = new ArrayList<>();
1660 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001661 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001662 mService.setPreferencesHelper(mPreferencesHelper);
1663 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001664 eq(mTestNotificationChannel.getId()), anyBoolean()))
1665 .thenReturn(mTestNotificationChannel);
1666 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001667 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001668 eq(channel2.getId()), anyBoolean()))
1669 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001670 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1671 eq(channel2), anyBoolean(), anyBoolean()))
1672 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001673
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001674 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001675 mBinderService.createNotificationChannels(PKG,
1676 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001677 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001678 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001679 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001680 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001681 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001682 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1683 }
1684
1685 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001686 public void testCreateChannelGroupNotifyListener() throws Exception {
1687 List<String> associations = new ArrayList<>();
1688 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001689 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001690 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001691 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1692 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1693
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001694 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001695 mBinderService.createNotificationChannelGroups(PKG,
1696 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001697 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001698 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001699 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001700 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001701 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001702 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1703 }
1704
1705 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001706 public void testUpdateChannelNotifyListener() throws Exception {
1707 List<String> associations = new ArrayList<>();
1708 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001709 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001710 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001711 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001712 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001713 eq(mTestNotificationChannel.getId()), anyBoolean()))
1714 .thenReturn(mTestNotificationChannel);
1715
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001716 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001717 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001718 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001719 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001720 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1721 }
1722
1723 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001724 public void testDeleteChannelNotifyListener() throws Exception {
1725 List<String> associations = new ArrayList<>();
1726 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001727 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001728 mService.setPreferencesHelper(mPreferencesHelper);
1729 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001730 eq(mTestNotificationChannel.getId()), anyBoolean()))
1731 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001732 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001733 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001734 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001735 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001736 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1737 }
1738
1739 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001740 public void testDeleteChannelGroupNotifyListener() throws Exception {
1741 List<String> associations = new ArrayList<>();
1742 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001743 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001744 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001745 mService.setPreferencesHelper(mPreferencesHelper);
1746 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001747 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001748 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001749 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001750 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001751 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001752 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1753 }
1754
1755 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001756 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001757 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001758 List<String> associations = new ArrayList<>();
1759 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001760 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001761 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001762 eq(mTestNotificationChannel.getId()), anyBoolean()))
1763 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001764
1765 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001766 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001767
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001768 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001769 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001770
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001771 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001772 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001773 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1774 }
1775
1776 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001777 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001778 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001779 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001780 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001781
1782 try {
1783 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001784 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001785 fail("listeners that don't have a companion device shouldn't be able to call this");
1786 } catch (SecurityException e) {
1787 // pass
1788 }
1789
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001790 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001791 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001792
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001793 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001794 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1795 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1796 }
1797
1798 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001799 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001800 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001801 List<String> associations = new ArrayList<>();
1802 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001803 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001804 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04001805 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001806 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001807 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001808
1809 try {
1810 mBinderService.updateNotificationChannelFromPrivilegedListener(
1811 null, PKG, UserHandle.ALL, mTestNotificationChannel);
1812 fail("incorrectly allowed a change to a user listener cannot see");
1813 } catch (SecurityException e) {
1814 // pass
1815 }
1816
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001817 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001818 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001819
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001820 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001821 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001822 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1823 }
1824
1825 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001826 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001827 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001828 List<String> associations = new ArrayList<>();
1829 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001830 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001831
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001832 mBinderService.getNotificationChannelsFromPrivilegedListener(
1833 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001834
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001835 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001836 anyString(), anyInt(), anyBoolean());
1837 }
1838
1839 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001840 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001841 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001842 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001843 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001844
1845 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001846 mBinderService.getNotificationChannelsFromPrivilegedListener(
1847 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001848 fail("listeners that don't have a companion device shouldn't be able to call this");
1849 } catch (SecurityException e) {
1850 // pass
1851 }
1852
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001853 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001854 anyString(), anyInt(), anyBoolean());
1855 }
1856
1857 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001858 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
1859 throws Exception {
1860 mService.setPreferencesHelper(mPreferencesHelper);
1861 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1862 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
1863
1864 mBinderService.getNotificationChannelsFromPrivilegedListener(
1865 null, PKG, Process.myUserHandle());
1866
1867 verify(mPreferencesHelper, times(1)).getNotificationChannels(
1868 anyString(), anyInt(), anyBoolean());
1869 }
1870
1871 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04001872 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
1873 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001874 mService.setPreferencesHelper(mPreferencesHelper);
1875 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1876 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
1877
1878 try {
1879 mBinderService.getNotificationChannelsFromPrivilegedListener(
1880 null, PKG, Process.myUserHandle());
1881 fail("listeners that don't have a companion device shouldn't be able to call this");
1882 } catch (SecurityException e) {
1883 // pass
1884 }
1885
1886 verify(mPreferencesHelper, never()).getNotificationChannels(
1887 anyString(), anyInt(), anyBoolean());
1888 }
1889
1890 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001891 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001892 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001893 List<String> associations = new ArrayList<>();
1894 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001895 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001896 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1897 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001898 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001899
1900 try {
1901 mBinderService.getNotificationChannelsFromPrivilegedListener(
1902 null, PKG, Process.myUserHandle());
1903 fail("listener getting channels from a user they cannot see");
1904 } catch (SecurityException e) {
1905 // pass
1906 }
1907
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001908 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001909 anyString(), anyInt(), anyBoolean());
1910 }
1911
1912 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001913 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001914 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001915 List<String> associations = new ArrayList<>();
1916 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001917 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001918
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001919 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1920 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001921
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001922 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001923 }
1924
1925 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001926 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001927 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001928 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001929 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001930
1931 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001932 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1933 null, PKG, Process.myUserHandle());
1934 fail("listeners that don't have a companion device shouldn't be able to call this");
1935 } catch (SecurityException e) {
1936 // pass
1937 }
1938
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001939 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001940 }
1941
1942 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001943 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001944 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001945 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001946 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001947 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1948 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001949 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001950 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001951 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1952 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001953 fail("listeners that don't have a companion device shouldn't be able to call this");
1954 } catch (SecurityException e) {
1955 // pass
1956 }
1957
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001958 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001959 }
Julia Reynoldsda781472017-04-12 09:41:16 -04001960
1961 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04001962 public void testHasCompanionDevice_failure() throws Exception {
1963 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
1964 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04001965 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04001966 }
Julia Reynolds727a7282017-04-13 10:54:01 -04001967
1968 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04001969 public void testHasCompanionDevice_noService() {
1970 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04001971
Julia Reynolds503ed942017-10-04 16:04:56 -04001972 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04001973 }
1974
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001975 @Test
1976 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
1977 final NotificationRecord nonGrouped = generateNotificationRecord(
1978 mTestNotificationChannel, 1, null, false);
1979 final NotificationRecord grouped = generateNotificationRecord(
1980 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001981 mService.addNotification(grouped);
1982 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001983
1984 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04001985 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001986 nonGrouped.getKey(), 100, null);
1987 snoozeNotificationRunnable.run();
1988
1989 // only snooze the one notification
1990 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04001991 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001992 }
1993
1994 @Test
1995 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
1996 final NotificationRecord parent = generateNotificationRecord(
1997 mTestNotificationChannel, 1, "group", true);
1998 final NotificationRecord child = generateNotificationRecord(
1999 mTestNotificationChannel, 2, "group", false);
2000 final NotificationRecord child2 = generateNotificationRecord(
2001 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002002 mService.addNotification(parent);
2003 mService.addNotification(child);
2004 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002005
2006 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002007 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002008 parent.getKey(), 100, null);
2009 snoozeNotificationRunnable.run();
2010
2011 // snooze parent and children
2012 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2013 }
2014
2015 @Test
2016 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2017 final NotificationRecord parent = generateNotificationRecord(
2018 mTestNotificationChannel, 1, "group", true);
2019 final NotificationRecord child = generateNotificationRecord(
2020 mTestNotificationChannel, 2, "group", false);
2021 final NotificationRecord child2 = generateNotificationRecord(
2022 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002023 mService.addNotification(parent);
2024 mService.addNotification(child);
2025 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002026
2027 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002028 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002029 child2.getKey(), 100, null);
2030 snoozeNotificationRunnable.run();
2031
2032 // only snooze the one child
2033 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2034 }
2035
2036 @Test
2037 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2038 final NotificationRecord parent = generateNotificationRecord(
2039 mTestNotificationChannel, 1, "group", true);
2040 assertTrue(parent.sbn.getNotification().isGroupSummary());
2041 final NotificationRecord child = generateNotificationRecord(
2042 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002043 mService.addNotification(parent);
2044 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002045
2046 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002047 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002048 child.getKey(), 100, null);
2049 snoozeNotificationRunnable.run();
2050
2051 // snooze child and summary
2052 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2053 }
2054
2055 @Test
2056 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2057 final NotificationRecord child = generateNotificationRecord(
2058 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002059 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002060
2061 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002062 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002063 child.getKey(), 100, null);
2064 snoozeNotificationRunnable.run();
2065
2066 // snooze child only
2067 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2068 }
2069
2070 @Test
2071 public void testPostGroupChild_unsnoozeParent() throws Exception {
2072 final NotificationRecord child = generateNotificationRecord(
2073 mTestNotificationChannel, 2, "group", false);
2074
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002075 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002076 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2077 waitForIdle();
2078
2079 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2080 anyString(), anyInt(), eq(child.getGroupKey()));
2081 }
2082
2083 @Test
2084 public void testPostNonGroup_noUnsnoozing() throws Exception {
2085 final NotificationRecord record = generateNotificationRecord(
2086 mTestNotificationChannel, 2, null, false);
2087
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002088 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002089 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2090 waitForIdle();
2091
2092 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2093 }
2094
2095 @Test
2096 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2097 final NotificationRecord parent = generateNotificationRecord(
2098 mTestNotificationChannel, 2, "group", true);
2099
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002100 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002101 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2102 waitForIdle();
2103
2104 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2105 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002106
2107 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002108 public void testSetListenerAccessForUser() throws Exception {
2109 UserHandle user = UserHandle.of(10);
2110 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002111 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2112
Julia Reynolds92febc32017-10-26 11:30:31 -04002113
2114 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2115 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2116 c.flattenToString(), user.getIdentifier(), true, true);
2117 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2118 c.flattenToString(), user.getIdentifier(), false, true);
2119 verify(mAssistants, never()).setPackageOrComponentEnabled(
2120 any(), anyInt(), anyBoolean(), anyBoolean());
2121 }
2122
2123 @Test
2124 public void testSetAssistantAccessForUser() throws Exception {
2125 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002126 List<UserInfo> uis = new ArrayList<>();
2127 UserInfo ui = new UserInfo();
2128 ui.id = 10;
2129 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002130 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002131 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2132
2133 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002134
2135 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2136 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2137 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002138 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002139 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2140 c.flattenToString(), user.getIdentifier(), false, true);
2141 verify(mListeners, never()).setPackageOrComponentEnabled(
2142 any(), anyInt(), anyBoolean(), anyBoolean());
2143 }
2144
2145 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002146 public void testGetAssistantAllowedForUser() throws Exception {
2147 UserHandle user = UserHandle.of(10);
2148 try {
2149 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2150 } catch (IllegalStateException e) {
2151 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2152 throw e;
2153 }
2154 }
2155 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2156 }
2157
2158 @Test
2159 public void testGetAssistantAllowed() throws Exception {
2160 try {
2161 mBinderService.getAllowedNotificationAssistant();
2162 } catch (IllegalStateException e) {
2163 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2164 throw e;
2165 }
2166 }
2167 verify(mAssistants, times(1)).getAllowedComponents(0);
2168 }
2169
2170 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002171 public void testSetDndAccessForUser() throws Exception {
2172 UserHandle user = UserHandle.of(10);
2173 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002174 mBinderService.setNotificationPolicyAccessGrantedForUser(
2175 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002176
2177 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2178 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2179 c.getPackageName(), user.getIdentifier(), true, true);
2180 verify(mAssistants, never()).setPackageOrComponentEnabled(
2181 any(), anyInt(), anyBoolean(), anyBoolean());
2182 verify(mListeners, never()).setPackageOrComponentEnabled(
2183 any(), anyInt(), anyBoolean(), anyBoolean());
2184 }
2185
2186 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002187 public void testSetListenerAccess() throws Exception {
2188 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002189 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002190
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002191 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002192 c.flattenToString(), 0, true, true);
2193 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2194 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002195 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002196 any(), anyInt(), anyBoolean(), anyBoolean());
2197 }
2198
2199 @Test
2200 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002201 List<UserInfo> uis = new ArrayList<>();
2202 UserInfo ui = new UserInfo();
2203 ui.id = 0;
2204 uis.add(ui);
2205 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002206 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002207
2208 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002209
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002210 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002211 c.flattenToString(), 0, true, true);
2212 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2213 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002214 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002215 any(), anyInt(), anyBoolean(), anyBoolean());
2216 }
2217
2218 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002219 public void testSetAssistantAccess_multiProfile() throws Exception {
2220 List<UserInfo> uis = new ArrayList<>();
2221 UserInfo ui = new UserInfo();
2222 ui.id = 0;
2223 uis.add(ui);
2224 UserInfo ui10 = new UserInfo();
2225 ui10.id = 10;
2226 uis.add(ui10);
2227 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2228 ComponentName c = ComponentName.unflattenFromString("package/Component");
2229
2230 mBinderService.setNotificationAssistantAccessGranted(c, true);
2231
2232 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2233 c.flattenToString(), 0, true, true);
2234 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2235 c.flattenToString(), 10, true, true);
2236 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2237 c.flattenToString(), 0, false, true);
2238 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2239 c.flattenToString(), 10, false, true);
2240 verify(mListeners, never()).setPackageOrComponentEnabled(
2241 any(), anyInt(), anyBoolean(), anyBoolean());
2242 }
2243
2244 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002245 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2246 ArrayList<ComponentName> componentList = new ArrayList<>();
2247 ComponentName c = ComponentName.unflattenFromString("package/Component");
2248 componentList.add(c);
2249 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002250 List<UserInfo> uis = new ArrayList<>();
2251 UserInfo ui = new UserInfo();
2252 ui.id = 0;
2253 uis.add(ui);
2254 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002255
Julia Reynolds4afe2642019-05-01 08:42:24 -04002256 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002257
2258 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2259 c.flattenToString(), 0, true, false);
2260 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2261 c.flattenToString(), 0, false, false);
2262 verify(mListeners, never()).setPackageOrComponentEnabled(
2263 any(), anyInt(), anyBoolean(), anyBoolean());
2264 }
2265
2266 @Test
2267 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002268 List<UserInfo> uis = new ArrayList<>();
2269 UserInfo ui = new UserInfo();
2270 ui.id = 10;
2271 uis.add(ui);
2272 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002273 ArrayList<ComponentName> componentList = new ArrayList<>();
2274 ComponentName c = ComponentName.unflattenFromString("package/Component");
2275 componentList.add(c);
2276 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002277 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002278
Julia Reynolds4afe2642019-05-01 08:42:24 -04002279 mBinderService.setNotificationAssistantAccessGrantedForUser(
2280 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002281
2282 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2283 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002284 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002285 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2286 c.flattenToString(), user.getIdentifier(), false, false);
2287 verify(mListeners, never()).setPackageOrComponentEnabled(
2288 any(), anyInt(), anyBoolean(), anyBoolean());
2289 }
2290
2291 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002292 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2293 throws Exception {
2294 List<UserInfo> uis = new ArrayList<>();
2295 UserInfo ui = new UserInfo();
2296 ui.id = 0;
2297 uis.add(ui);
2298 UserInfo ui10 = new UserInfo();
2299 ui10.id = 10;
2300 uis.add(ui10);
2301 UserHandle user = ui.getUserHandle();
2302 ArrayList<ComponentName> componentList = new ArrayList<>();
2303 ComponentName c = ComponentName.unflattenFromString("package/Component");
2304 componentList.add(c);
2305 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2306 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2307
2308 mBinderService.setNotificationAssistantAccessGrantedForUser(
2309 null, user.getIdentifier(), true);
2310
2311 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2312 c.flattenToString(), user.getIdentifier(), true, false);
2313 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2314 c.flattenToString(), ui10.id, true, false);
2315 verify(mAssistants).setUserSet(0, true);
2316 verify(mAssistants).setUserSet(10, true);
2317 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2318 c.flattenToString(), user.getIdentifier(), false, false);
2319 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2320 c.flattenToString(), ui10.id, false, false);
2321 verify(mListeners, never()).setPackageOrComponentEnabled(
2322 any(), anyInt(), anyBoolean(), anyBoolean());
2323 }
2324
2325 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002326 public void testSetDndAccess() throws Exception {
2327 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002328
2329 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002330
2331 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2332 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002333 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002334 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002335 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002336 any(), anyInt(), anyBoolean(), anyBoolean());
2337 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002338
2339 @Test
2340 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2341 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2342 ComponentName c = ComponentName.unflattenFromString("package/Component");
2343 mBinderService.setNotificationListenerAccessGranted(c, true);
2344
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002345 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002346 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002347 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002348 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002349 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002350 any(), anyInt(), anyBoolean(), anyBoolean());
2351 }
2352
2353 @Test
2354 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2355 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2356 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002357 List<UserInfo> uis = new ArrayList<>();
2358 UserInfo ui = new UserInfo();
2359 ui.id = 0;
2360 uis.add(ui);
2361 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2362
Julia Reynolds68263d12017-06-21 14:21:19 -04002363 mBinderService.setNotificationAssistantAccessGranted(c, true);
2364
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002365 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002366 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002367 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002368 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002369 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002370 any(), anyInt(), anyBoolean(), anyBoolean());
2371 }
2372
2373 @Test
2374 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2375 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2376 ComponentName c = ComponentName.unflattenFromString("package/Component");
2377 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2378
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002379 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002380 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002381 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002382 anyString(), anyInt(), anyBoolean(), anyBoolean());
2383 verify(mAssistants, never()).setPackageOrComponentEnabled(
2384 any(), anyInt(), anyBoolean(), anyBoolean());
2385 }
2386
2387 @Test
2388 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2389 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2390 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2391 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002392
2393 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002394
2395 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2396 c.flattenToString(), 0, true, true);
2397 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002398 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002399 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002400 any(), anyInt(), anyBoolean(), anyBoolean());
2401 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002402
2403 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002404 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2405 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2406 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2407 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002408 List<UserInfo> uis = new ArrayList<>();
2409 UserInfo ui = new UserInfo();
2410 ui.id = 0;
2411 uis.add(ui);
2412 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2413
2414 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002415
2416 verify(mListeners, never()).setPackageOrComponentEnabled(
2417 anyString(), anyInt(), anyBoolean(), anyBoolean());
2418 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2419 c.flattenToString(), 0, false, true);
2420 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2421 c.flattenToString(), 0, true, true);
2422 }
2423
2424 @Test
2425 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2426 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2427 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2428 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002429
2430 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002431
2432 verify(mListeners, never()).setPackageOrComponentEnabled(
2433 anyString(), anyInt(), anyBoolean(), anyBoolean());
2434 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2435 c.getPackageName(), 0, true, true);
2436 verify(mAssistants, never()).setPackageOrComponentEnabled(
2437 any(), anyInt(), anyBoolean(), anyBoolean());
2438 }
2439
2440 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002441 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2442 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002443 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002444 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002445 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002446 runnable.run();
2447 waitForIdle();
2448
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002449 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002450 }
2451
2452 @Test
2453 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2454 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002455 NotificationRecord r =
2456 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002457 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002458
2459 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002460 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002461 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002462 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002463 runnable.run();
2464 waitForIdle();
2465
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002466 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002467 }
2468
2469 @Test
2470 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2471 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002472 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2473 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002474 mService.addNotification(r);
2475 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002476
2477 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002478 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002479 runnable.run();
2480 waitForIdle();
2481
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002482 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002483 }
Beverly40239d92017-07-07 10:20:41 -04002484
Julia Reynolds4db59552017-06-30 13:34:01 -04002485 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002486 public void testDontAutogroupIfCritical() throws Exception {
2487 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2488 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2489 mService.addEnqueuedNotification(r);
2490 NotificationManagerService.PostNotificationRunnable runnable =
2491 mService.new PostNotificationRunnable(r.getKey());
2492 runnable.run();
2493
2494 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2495 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2496 runnable = mService.new PostNotificationRunnable(r.getKey());
2497 mService.addEnqueuedNotification(r);
2498
2499 runnable.run();
2500 waitForIdle();
2501
2502 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2503 }
2504
2505 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002506 public void testNoFakeColorizedPermission() throws Exception {
2507 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2508 Notification.Builder nb = new Notification.Builder(mContext,
2509 mTestNotificationChannel.getId())
2510 .setContentTitle("foo")
2511 .setColorized(true)
2512 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2513 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002514 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
2515 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002516 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2517
2518 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2519 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2520 waitForIdle();
2521
Julia Reynolds503ed942017-10-04 16:04:56 -04002522 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds4db59552017-06-30 13:34:01 -04002523 PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
2524
2525 assertFalse(posted.getNotification().isColorized());
2526 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002527
2528 @Test
2529 public void testGetNotificationCountLocked() throws Exception {
2530 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002531 NotificationRecord r =
2532 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002533 mService.addEnqueuedNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002534 }
2535 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002536 NotificationRecord r =
2537 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002538 mService.addNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002539 }
2540
2541 // another package
2542 Notification n =
2543 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2544 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2545 .build();
2546
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002547 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2548 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002549 NotificationRecord otherPackage =
2550 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002551 mService.addEnqueuedNotification(otherPackage);
2552 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002553
2554 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002555 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002556 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002557 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002558 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002559 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002560 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002561 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002562
2563 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002564 assertEquals(39,
Julia Reynolds503ed942017-10-04 16:04:56 -04002565 mService.getNotificationCountLocked(PKG, userId, 0, "tag"));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002566 }
2567
2568 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002569 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002570 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002571 mService.setRankingHandler(rh);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002572
2573 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002574 mService.addNotification(r);
2575 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002576
2577 verify(rh, times(1)).requestSort();
2578 }
2579
2580 @Test
2581 public void testRemoveAutogroup_requestsSort() throws Exception {
2582 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002583 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002584
2585 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2586 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002587 mService.addNotification(r);
2588 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002589
Julia Reynolds51710712017-07-19 13:48:07 -04002590 verify(rh, times(1)).requestSort();
2591 }
2592
2593 @Test
2594 public void testReaddAutogroup_noSort() throws Exception {
2595 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002596 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002597
2598 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2599 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002600 mService.addNotification(r);
2601 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002602
2603 verify(rh, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002604 }
2605
2606 @Test
2607 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002608 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002609 NotificationManagerService.WorkerHandler handler = mock(
2610 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002611 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002612
2613 Map<String, Answer> answers = getSignalExtractorSideEffects();
2614 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002615 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002616 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002617 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002618
2619 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2620
Julia Reynolds503ed942017-10-04 16:04:56 -04002621 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002622 }
2623 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2624 }
2625
2626 @Test
2627 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002628 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002629 NotificationManagerService.WorkerHandler handler = mock(
2630 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002631 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002632
2633 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002634 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002635
Julia Reynolds503ed942017-10-04 16:04:56 -04002636 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002637 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002638 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002639
2640 @Test
2641 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002642 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002643 + "<ranking></ranking>"
2644 + "<enabled_listeners>"
2645 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2646 + "</enabled_listeners>"
2647 + "<enabled_assistants>"
2648 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2649 + "</enabled_assistants>"
2650 + "<dnd_apps>"
2651 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2652 + "</dnd_apps>"
2653 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002654 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002655 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2656 false,
2657 UserHandle.USER_ALL);
2658 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2659 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2660 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002661
2662 // numbers are inflated for setup
2663 verify(mListeners, times(1)).migrateToXml();
2664 verify(mConditionProviders, times(1)).migrateToXml();
2665 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002666 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002667 }
2668
2669 @Test
2670 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2671 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002672 + "<ranking></ranking>"
2673 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002674 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002675 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2676 false,
2677 UserHandle.USER_ALL);
2678 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2679 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2680 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002681
2682 // numbers are inflated for setup
2683 verify(mListeners, times(2)).migrateToXml();
2684 verify(mConditionProviders, times(2)).migrateToXml();
2685 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002686 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002687 }
2688
Annie Meng8b646fd2019-02-01 18:46:42 +00002689 @Test
2690 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2691 final String policyXml = "<notification-policy version=\"1\">"
2692 + "<ranking></ranking>"
2693 + "<enabled_listeners>"
2694 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2695 + "</enabled_listeners>"
2696 + "<enabled_assistants>"
2697 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2698 + "</enabled_assistants>"
2699 + "<dnd_apps>"
2700 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2701 + "</dnd_apps>"
2702 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002703 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00002704 mService.readPolicyXml(
2705 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2706 true,
2707 10);
2708 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2709 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2710 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2711 }
2712
2713 @Test
2714 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2715 final String policyXml = "<notification-policy version=\"1\">"
2716 + "<ranking></ranking>"
2717 + "<enabled_listeners>"
2718 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2719 + "</enabled_listeners>"
2720 + "<enabled_assistants>"
2721 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2722 + "</enabled_assistants>"
2723 + "<dnd_apps>"
2724 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2725 + "</dnd_apps>"
2726 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002727 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00002728 mService.readPolicyXml(
2729 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2730 true,
2731 10);
2732 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
2733 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
2734 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
2735 }
Beverlyd4f96492017-08-02 13:36:11 -04002736
2737 @Test
2738 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
2739 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002740 mService.mZenModeHelper = mZenModeHelper;
2741 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04002742 new Intent(Intent.ACTION_LOCALE_CHANGED));
2743
2744 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
2745 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002746
2747 @Test
2748 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06002749 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002750 final ApplicationInfo legacy = new ApplicationInfo();
2751 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
2752 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
2753 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002754 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
2755 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002756 getContext().setMockPackageManager(mPackageManagerClient);
2757
2758 Notification.Builder nb = new Notification.Builder(mContext,
2759 NotificationChannel.DEFAULT_CHANNEL_ID)
2760 .setContentTitle("foo")
2761 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002762 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002763 .setPriority(Notification.PRIORITY_MIN);
2764
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002765 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
2766 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002767
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002768 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
2769 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002770 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002771
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002772 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002773 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002774
2775 nb = new Notification.Builder(mContext)
2776 .setContentTitle("foo")
2777 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002778 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002779 .setPriority(Notification.PRIORITY_MIN);
2780
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002781 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
2782 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002783
2784 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
2785 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2786 waitForIdle();
2787 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002788 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002789
2790 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04002791 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002792 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
2793 }
Julia Reynolds503ed942017-10-04 16:04:56 -04002794
2795 @Test
2796 public void testStats_updatedOnDirectReply() throws Exception {
2797 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2798 mService.addNotification(r);
2799
2800 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
2801 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00002802 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04002803 }
2804
2805 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002806 public void testStats_updatedOnUserExpansion() throws Exception {
2807 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002808 mService.addNotification(r);
2809
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002810 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
2811 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002812 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002813 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002814
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002815 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
2816 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002817 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002818 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2819 }
2820
2821 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002822 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
2823 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2824 mService.addNotification(r);
2825
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002826 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
2827 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002828 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002829 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
2830
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002831 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
2832 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002833 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002834 verify(mAssistants).notifyAssistantExpansionChangedLocked(
2835 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002836 }
2837
2838 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04002839 public void testStats_updatedOnViewSettings() throws Exception {
2840 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2841 mService.addNotification(r);
2842
2843 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
2844 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
2845 }
2846
2847 @Test
2848 public void testStats_updatedOnVisibilityChanged() throws Exception {
2849 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2850 mService.addNotification(r);
2851
Dieter Hsud39f0d52018-04-14 02:08:30 +08002852 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002853 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2854 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
2855 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2856 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2857 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
2858 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2859 }
2860
2861 @Test
2862 public void testStats_dismissalSurface() throws Exception {
2863 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2864 mService.addNotification(r);
2865
Dieter Hsud39f0d52018-04-14 02:08:30 +08002866 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002867 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002868 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2869 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04002870 waitForIdle();
2871
2872 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
2873 }
2874
2875 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002876 public void testStats_dismissalSentiment() throws Exception {
2877 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2878 mService.addNotification(r);
2879
2880 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2881 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2882 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2883 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
2884 waitForIdle();
2885
2886 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
2887 r.getStats().getDismissalSentiment());
2888 }
2889
2890 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002891 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002892 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2893 mService.addNotification(r);
2894 NotificationManagerService.WorkerHandler handler = mock(
2895 NotificationManagerService.WorkerHandler.class);
2896 mService.setHandler(handler);
2897
Julia Reynolds70aaea72018-07-13 13:38:34 -04002898 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2899
Julia Reynolds503ed942017-10-04 16:04:56 -04002900 Bundle signals = new Bundle();
2901 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04002902 USER_SENTIMENT_NEGATIVE);
2903 Adjustment adjustment = new Adjustment(
2904 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2905 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2906
2907 waitForIdle();
2908
2909 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2910 }
2911
2912 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05002913 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002914 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2915 mService.addNotification(r);
2916 NotificationManagerService.WorkerHandler handler = mock(
2917 NotificationManagerService.WorkerHandler.class);
2918 mService.setHandler(handler);
2919
2920 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04002921 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002922 Adjustment adjustment = new Adjustment(
2923 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2924 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
2925 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2926
2927 waitForIdle();
2928
2929 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2930 verify(handler, times(1)).scheduleCancelNotification(any());
2931 }
2932
2933 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002934 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
2935 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2936 mService.addEnqueuedNotification(r);
2937 NotificationManagerService.WorkerHandler handler = mock(
2938 NotificationManagerService.WorkerHandler.class);
2939 mService.setHandler(handler);
2940 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
2941
2942 Bundle signals = new Bundle();
2943 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2944 USER_SENTIMENT_NEGATIVE);
2945 Adjustment adjustment = new Adjustment(
2946 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2947 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
2948
2949 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
2950 }
2951
2952 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04002953 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05002954 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2955 mService.addEnqueuedNotification(r);
2956 NotificationManagerService.WorkerHandler handler = mock(
2957 NotificationManagerService.WorkerHandler.class);
2958 mService.setHandler(handler);
2959 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
2960
2961 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04002962 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002963 Adjustment adjustment = new Adjustment(
2964 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2965 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
2966
2967 assertEquals(IMPORTANCE_LOW, r.getImportance());
2968 }
2969
2970 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002971 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
2972 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2973 mService.addEnqueuedNotification(r);
2974 NotificationManagerService.WorkerHandler handler = mock(
2975 NotificationManagerService.WorkerHandler.class);
2976 mService.setHandler(handler);
2977 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2978
2979 Bundle signals = new Bundle();
2980 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2981 USER_SENTIMENT_NEGATIVE);
2982 Adjustment adjustment = new Adjustment(
2983 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2984 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
2985
2986 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
2987
2988 waitForIdle();
2989
2990 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2991 }
2992
2993 @Test
2994 public void testUserSentimentChangeTriggersUpdate() throws Exception {
2995 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2996 mService.addNotification(r);
2997 NotificationManagerService.WorkerHandler handler = mock(
2998 NotificationManagerService.WorkerHandler.class);
2999 mService.setHandler(handler);
3000 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3001
3002 Bundle signals = new Bundle();
3003 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3004 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003005 Adjustment adjustment = new Adjustment(
3006 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3007 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3008
3009 waitForIdle();
3010
3011 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3012 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003013
3014 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003015 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3016 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3017 mService.addNotification(r);
3018 NotificationManagerService.WorkerHandler handler = mock(
3019 NotificationManagerService.WorkerHandler.class);
3020 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003021 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003022
3023 Bundle signals = new Bundle();
3024 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003025 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003026 Adjustment adjustment = new Adjustment(
3027 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3028 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3029
3030 waitForIdle();
3031
3032 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3033 }
3034
3035 @Test
3036 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3037 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3038 mService.addEnqueuedNotification(r);
3039 NotificationManagerService.WorkerHandler handler = mock(
3040 NotificationManagerService.WorkerHandler.class);
3041 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003042 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003043
3044 Bundle signals = new Bundle();
3045 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003046 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003047 Adjustment adjustment = new Adjustment(
3048 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3049 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3050
Julia Reynolds70aaea72018-07-13 13:38:34 -04003051 assertEquals(USER_SENTIMENT_NEGATIVE,
Julia Reynolds666ccf02018-06-18 10:19:20 -04003052 r.getUserSentiment());
3053 }
3054
3055 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003056 public void testRestore() throws Exception {
3057 int systemChecks = mService.countSystemChecks;
3058 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
3059 assertEquals(1, mService.countSystemChecks - systemChecks);
3060 }
3061
3062 @Test
3063 public void testBackup() throws Exception {
3064 int systemChecks = mService.countSystemChecks;
3065 mBinderService.getBackupPayload(1);
3066 assertEquals(1, mService.countSystemChecks - systemChecks);
3067 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003068
3069 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003070 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003071 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003072 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003073 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3074 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003075 message1.setData("",
3076 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003077 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003078 message2.setData("",
3079 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003080
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003081 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003082 .setContentTitle("foo")
3083 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3084 .setStyle(new Notification.MessagingStyle("")
3085 .addMessage(message1)
3086 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003087 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3088 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003089
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003090 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003091 reset(mUgm);
3092 reset(mUgmInternal);
3093 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003094 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
3095 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003096 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003097 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003098 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003099 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3100
3101 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003102 .setContentTitle("foo")
3103 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3104 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003105 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3106 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003107
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003108 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003109 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003110 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
3111 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003112 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3113 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003114
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003115 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003116 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003117 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
3118 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003119 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003120 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003121
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003122 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003123 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003124 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
3125 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003126 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003127 anyInt(), anyInt());
3128 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003129
3130 @Test
Robin Leed107af62018-04-27 13:55:56 +02003131 public void testVisitUris() throws Exception {
3132 final Uri audioContents = Uri.parse("content://com.example/audio");
3133 final Uri backgroundImage = Uri.parse("content://com.example/background");
3134
3135 Bundle extras = new Bundle();
3136 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3137 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3138
3139 Notification n = new Notification.Builder(mContext, "a")
3140 .setContentTitle("notification with uris")
3141 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3142 .addExtras(extras)
3143 .build();
3144
3145 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3146 n.visitUris(visitor);
3147 verify(visitor, times(1)).accept(eq(audioContents));
3148 verify(visitor, times(1)).accept(eq(backgroundImage));
3149 }
3150
3151 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003152 public void testSetNotificationPolicy_preP_setOldFields() {
3153 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3154 mService.mZenModeHelper = mZenModeHelper;
3155 NotificationManager.Policy userPolicy =
3156 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3157 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3158
3159 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3160 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3161
3162 int expected = SUPPRESSED_EFFECT_BADGE
3163 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003164 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3165 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003166 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3167
3168 assertEquals(expected, actual);
3169 }
3170
3171 @Test
3172 public void testSetNotificationPolicy_preP_setNewFields() {
3173 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3174 mService.mZenModeHelper = mZenModeHelper;
3175 NotificationManager.Policy userPolicy =
3176 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3177 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3178
3179 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3180 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3181
3182 int expected = SUPPRESSED_EFFECT_BADGE;
3183 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3184
3185 assertEquals(expected, actual);
3186 }
3187
3188 @Test
3189 public void testSetNotificationPolicy_preP_setOldNewFields() {
3190 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3191 mService.mZenModeHelper = mZenModeHelper;
3192 NotificationManager.Policy userPolicy =
3193 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3194 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3195
3196 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3197 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3198
3199 int expected =
3200 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3201 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3202
3203 assertEquals(expected, actual);
3204 }
3205
3206 @Test
3207 public void testSetNotificationPolicy_P_setOldFields() {
3208 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3209 mService.mZenModeHelper = mZenModeHelper;
3210 NotificationManager.Policy userPolicy =
3211 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3212 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3213
3214 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3215 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3216
3217 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3218 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3219 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3220 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3221
3222 assertEquals(expected, actual);
3223 }
3224
3225 @Test
3226 public void testSetNotificationPolicy_P_setNewFields() {
3227 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3228 mService.mZenModeHelper = mZenModeHelper;
3229 NotificationManager.Policy userPolicy =
3230 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3231 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3232
3233 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3234 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3235 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3236
3237 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3238 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3239 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3240 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3241
3242 assertEquals(expected, actual);
3243 }
3244
3245 @Test
3246 public void testSetNotificationPolicy_P_setOldNewFields() {
3247 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3248 mService.mZenModeHelper = mZenModeHelper;
3249 NotificationManager.Policy userPolicy =
3250 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3251 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3252
3253 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3254 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3255
3256 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3257 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3258
3259 assertEquals(expected, actual);
3260
3261 appPolicy = new NotificationManager.Policy(0, 0, 0,
3262 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3263 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3264
3265 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3266 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3267 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3268
3269 assertEquals(expected, actual);
3270 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003271
3272 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003273 public void testVisualDifference_foreground() {
3274 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3275 .setContentTitle("foo");
3276 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3277 nb1.build(), new UserHandle(mUid), null, 0);
3278 NotificationRecord r1 =
3279 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3280
3281 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3282 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3283 .setContentTitle("bar");
3284 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3285 nb2.build(), new UserHandle(mUid), null, 0);
3286 NotificationRecord r2 =
3287 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3288
3289 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3290 }
3291
3292 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003293 public void testVisualDifference_diffTitle() {
3294 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3295 .setContentTitle("foo");
3296 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3297 nb1.build(), new UserHandle(mUid), null, 0);
3298 NotificationRecord r1 =
3299 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3300
3301 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3302 .setContentTitle("bar");
3303 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3304 nb2.build(), new UserHandle(mUid), null, 0);
3305 NotificationRecord r2 =
3306 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3307
3308 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3309 }
3310
3311 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003312 public void testVisualDifference_inboxStyle() {
3313 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3314 .setStyle(new Notification.InboxStyle()
3315 .addLine("line1").addLine("line2"));
3316 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3317 nb1.build(), new UserHandle(mUid), null, 0);
3318 NotificationRecord r1 =
3319 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3320
3321 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3322 .setStyle(new Notification.InboxStyle()
3323 .addLine("line1").addLine("line2_changed"));
3324 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3325 nb2.build(), new UserHandle(mUid), null, 0);
3326 NotificationRecord r2 =
3327 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3328
3329 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3330
3331 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3332 .setStyle(new Notification.InboxStyle()
3333 .addLine("line1"));
3334 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3335 nb3.build(), new UserHandle(mUid), null, 0);
3336 NotificationRecord r3 =
3337 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3338
3339 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3340
3341 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3342 .setStyle(new Notification.InboxStyle()
3343 .addLine("line1").addLine("line2").addLine("line3"));
3344 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3345 nb4.build(), new UserHandle(mUid), null, 0);
3346 NotificationRecord r4 =
3347 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3348
3349 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3350
3351 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3352 .setContentText("not an inbox");
3353 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3354 nb5.build(), new UserHandle(mUid), null, 0);
3355 NotificationRecord r5 =
3356 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3357
3358 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3359 }
3360
3361 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003362 public void testVisualDifference_diffText() {
3363 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3364 .setContentText("foo");
3365 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3366 nb1.build(), new UserHandle(mUid), null, 0);
3367 NotificationRecord r1 =
3368 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3369
3370 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3371 .setContentText("bar");
3372 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3373 nb2.build(), new UserHandle(mUid), null, 0);
3374 NotificationRecord r2 =
3375 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3376
3377 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3378 }
3379
3380 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003381 public void testVisualDifference_sameText() {
3382 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3383 .setContentText("foo");
3384 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3385 nb1.build(), new UserHandle(mUid), null, 0);
3386 NotificationRecord r1 =
3387 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3388
3389 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3390 .setContentText("foo");
3391 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3392 nb2.build(), new UserHandle(mUid), null, 0);
3393 NotificationRecord r2 =
3394 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3395
3396 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3397 }
3398
3399 @Test
3400 public void testVisualDifference_sameTextButStyled() {
3401 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3402 .setContentText(Html.fromHtml("<b>foo</b>"));
3403 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3404 nb1.build(), new UserHandle(mUid), null, 0);
3405 NotificationRecord r1 =
3406 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3407
3408 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3409 .setContentText(Html.fromHtml("<b>foo</b>"));
3410 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3411 nb2.build(), new UserHandle(mUid), null, 0);
3412 NotificationRecord r2 =
3413 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3414
3415 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3416 }
3417
3418 @Test
3419 public void testVisualDifference_diffTextButStyled() {
3420 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3421 .setContentText(Html.fromHtml("<b>foo</b>"));
3422 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3423 nb1.build(), new UserHandle(mUid), null, 0);
3424 NotificationRecord r1 =
3425 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3426
3427 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3428 .setContentText(Html.fromHtml("<b>bar</b>"));
3429 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3430 nb2.build(), new UserHandle(mUid), null, 0);
3431 NotificationRecord r2 =
3432 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3433
3434 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3435 }
3436
3437 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003438 public void testVisualDifference_diffProgress() {
3439 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3440 .setProgress(100, 90, false);
3441 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3442 nb1.build(), new UserHandle(mUid), null, 0);
3443 NotificationRecord r1 =
3444 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3445
3446 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3447 .setProgress(100, 100, false);
3448 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3449 nb2.build(), new UserHandle(mUid), null, 0);
3450 NotificationRecord r2 =
3451 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3452
3453 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3454 }
3455
3456 @Test
3457 public void testVisualDifference_diffProgressNotDone() {
3458 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3459 .setProgress(100, 90, false);
3460 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3461 nb1.build(), new UserHandle(mUid), null, 0);
3462 NotificationRecord r1 =
3463 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3464
3465 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3466 .setProgress(100, 91, false);
3467 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3468 nb2.build(), new UserHandle(mUid), null, 0);
3469 NotificationRecord r2 =
3470 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3471
3472 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3473 }
Beverly5a20a5e2018-03-06 15:02:44 -05003474
3475 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003476 public void testVisualDifference_sameProgressStillDone() {
3477 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3478 .setProgress(100, 100, false);
3479 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3480 nb1.build(), new UserHandle(mUid), null, 0);
3481 NotificationRecord r1 =
3482 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3483
3484 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3485 .setProgress(100, 100, false);
3486 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3487 nb2.build(), new UserHandle(mUid), null, 0);
3488 NotificationRecord r2 =
3489 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3490
3491 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3492 }
3493
3494 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003495 public void testVisualDifference_summary() {
3496 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3497 .setGroup("bananas")
3498 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3499 .setContentText("foo");
3500 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3501 nb1.build(), new UserHandle(mUid), null, 0);
3502 NotificationRecord r1 =
3503 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3504
3505 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3506 .setGroup("bananas")
3507 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3508 .setContentText("bar");
3509 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3510 nb2.build(), new UserHandle(mUid), null, 0);
3511 NotificationRecord r2 =
3512 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3513
3514 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3515 }
3516
3517 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003518 public void testVisualDifference_summaryNewNotification() {
3519 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3520 .setGroup("bananas")
3521 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3522 .setContentText("bar");
3523 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3524 nb2.build(), new UserHandle(mUid), null, 0);
3525 NotificationRecord r2 =
3526 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3527
3528 assertFalse(mService.isVisuallyInterruptive(null, r2));
3529 }
3530
3531 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003532 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3533 // post 2 notification from this package
3534 final NotificationRecord notif1 = generateNotificationRecord(
3535 mTestNotificationChannel, 1, null, true);
3536 final NotificationRecord notif2 = generateNotificationRecord(
3537 mTestNotificationChannel, 2, null, false);
3538 mService.addNotification(notif1);
3539 mService.addNotification(notif2);
3540
3541 // on broadcast, hide the 2 notifications
3542 mService.simulatePackageSuspendBroadcast(true, PKG);
3543 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3544 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3545 assertEquals(2, captorHide.getValue().size());
3546
3547 // on broadcast, unhide the 2 notifications
3548 mService.simulatePackageSuspendBroadcast(false, PKG);
3549 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3550 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3551 assertEquals(2, captorUnhide.getValue().size());
3552 }
3553
3554 @Test
3555 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3556 // post 2 notification from this package
3557 final NotificationRecord notif1 = generateNotificationRecord(
3558 mTestNotificationChannel, 1, null, true);
3559 final NotificationRecord notif2 = generateNotificationRecord(
3560 mTestNotificationChannel, 2, null, false);
3561 mService.addNotification(notif1);
3562 mService.addNotification(notif2);
3563
3564 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3565 mService.simulatePackageSuspendBroadcast(true, "test_package");
3566 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3567 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3568 assertEquals(0, captor.getValue().size());
3569 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003570
3571 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003572 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3573 // Post 2 notifications from 2 packages
3574 NotificationRecord pkgA = new NotificationRecord(mContext,
3575 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3576 mService.addNotification(pkgA);
3577 NotificationRecord pkgB = new NotificationRecord(mContext,
3578 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3579 mService.addNotification(pkgB);
3580
3581 // on broadcast, hide one of the packages
3582 mService.simulatePackageDistractionBroadcast(
3583 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3584 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3585 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3586 assertEquals(1, captorHide.getValue().size());
3587 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3588
3589 // on broadcast, unhide the package
3590 mService.simulatePackageDistractionBroadcast(
3591 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3592 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3593 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3594 assertEquals(1, captorUnhide.getValue().size());
3595 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3596 }
3597
3598 @Test
3599 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3600 // Post 2 notifications from 2 packages
3601 NotificationRecord pkgA = new NotificationRecord(mContext,
3602 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3603 mService.addNotification(pkgA);
3604 NotificationRecord pkgB = new NotificationRecord(mContext,
3605 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3606 mService.addNotification(pkgB);
3607
3608 // on broadcast, hide one of the packages
3609 mService.simulatePackageDistractionBroadcast(
3610 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3611 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3612 verify(mListeners, times(2)).notifyHiddenLocked(captorHide.capture());
3613 assertEquals(2, captorHide.getValue().size());
3614 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3615 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3616
3617 // on broadcast, unhide the package
3618 mService.simulatePackageDistractionBroadcast(
3619 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3620 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3621 verify(mListeners, times(2)).notifyUnhiddenLocked(captorUnhide.capture());
3622 assertEquals(2, captorUnhide.getValue().size());
3623 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3624 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3625 }
3626
3627 @Test
3628 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3629 // post notification from this package
3630 final NotificationRecord notif1 = generateNotificationRecord(
3631 mTestNotificationChannel, 1, null, true);
3632 mService.addNotification(notif1);
3633
3634 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3635 mService.simulatePackageDistractionBroadcast(
3636 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3637 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3638 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3639 assertEquals(0, captor.getValue().size());
3640 }
3641
3642 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003643 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3644 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3645 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3646 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3647 .thenReturn(new String[] {"a", "b", "c"});
3648 when(mContext.getResources()).thenReturn(mResources);
3649
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003650 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003651 }
3652
3653 @Test
3654 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3655 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3656 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3657 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3658 .thenReturn(new String[] {"a", "b", "c"});
3659 when(mContext.getResources()).thenReturn(mResources);
3660
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003661 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003662 }
3663
3664 @Test
3665 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3666 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3667 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3668 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3669 .thenReturn(new String[] {"a", "b", "c"});
3670 when(mContext.getResources()).thenReturn(mResources);
3671
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003672 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003673 }
3674
3675 @Test
3676 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3677 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3678 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3679 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3680 .thenReturn(new String[] {"a", "b", "c"});
3681 when(mContext.getResources()).thenReturn(mResources);
3682
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003683 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003684 }
3685
3686 @Test
3687 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3688 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3689 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3690 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3691 .thenReturn(new String[] {"a", "b", "c"});
3692 when(mContext.getResources()).thenReturn(mResources);
3693
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003694 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003695 }
3696
3697 @Test
3698 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
3699 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3700 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3701 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3702 .thenReturn(new String[] {"a", "b", "c"});
3703 when(mContext.getResources()).thenReturn(mResources);
3704
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003705 assertEquals(true, mService.canUseManagedServices("d", 0, null));
3706 }
3707
3708 @Test
3709 public void testCanUseManagedServices_hasPermission() throws Exception {
3710 when(mPackageManager.checkPermission("perm", "pkg", 0))
3711 .thenReturn(PackageManager.PERMISSION_GRANTED);
3712
3713 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
3714 }
3715
3716 @Test
3717 public void testCanUseManagedServices_noPermission() throws Exception {
3718 when(mPackageManager.checkPermission("perm", "pkg", 0))
3719 .thenReturn(PackageManager.PERMISSION_DENIED);
3720
3721 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
3722 }
3723
3724 @Test
3725 public void testCanUseManagedServices_permDoesNotMatter() {
3726 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003727 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003728
3729 @Test
3730 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
3731 final NotificationRecord r = generateNotificationRecord(
3732 mTestNotificationChannel, 1, null, true);
3733 r.setTextChanged(true);
3734 mService.addNotification(r);
3735
3736 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
3737 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
3738 new NotificationVisibility[]{});
3739
3740 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3741 }
3742
3743 @Test
3744 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
3745 throws RemoteException {
3746 final NotificationRecord r = generateNotificationRecord(
3747 mTestNotificationChannel, 1, null, true);
3748 r.setTextChanged(true);
3749 mService.addNotification(r);
3750
3751 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
3752
3753 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3754 }
3755
3756 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003757 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003758 throws RemoteException {
3759 final NotificationRecord r = generateNotificationRecord(
3760 mTestNotificationChannel, 1, null, true);
3761 r.setInterruptive(true);
3762 mService.addNotification(r);
3763
3764 mService.maybeRecordInterruptionLocked(r);
3765 mService.maybeRecordInterruptionLocked(r);
3766
3767 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
3768 anyString(), anyString(), anyInt());
3769 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003770
3771 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08003772 public void testBubble() throws Exception {
3773 mBinderService.setBubblesAllowed(PKG, mUid, false);
3774 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05003775 }
3776
3777 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08003778 public void testUserApprovedBubblesForPackage() throws Exception {
3779 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3780 mBinderService.setBubblesAllowed(PKG, mUid, true);
3781 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3782 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3783 }
3784
3785 @Test
3786 public void testUserRejectsBubblesForPackage() throws Exception {
3787 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3788 mBinderService.setBubblesAllowed(PKG, mUid, false);
3789 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3790 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3791 }
3792
3793 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003794 public void testIsCallerInstantApp_primaryUser() throws Exception {
3795 ApplicationInfo info = new ApplicationInfo();
3796 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3797 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04003798 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003799
Julia Reynolds268647a2018-10-25 16:54:27 -04003800 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003801
3802 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04003803 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003804 }
3805
3806 @Test
3807 public void testIsCallerInstantApp_secondaryUser() throws Exception {
3808 ApplicationInfo info = new ApplicationInfo();
3809 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3810 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3811 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04003812 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003813
Julia Reynolds268647a2018-10-25 16:54:27 -04003814 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003815 }
3816
3817 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04003818 public void testIsCallerInstantApp_userAllNotification() throws Exception {
3819 ApplicationInfo info = new ApplicationInfo();
3820 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3821 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
3822 .thenReturn(info);
3823 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3824
3825 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
3826
3827 info.privateFlags = 0;
3828 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
3829 }
3830
3831 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003832 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
3833 ApplicationInfo info = new ApplicationInfo();
3834 info.uid = Binder.getCallingUid();
3835 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3836 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3837
3838 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
3839
3840 assertEquals(info.uid, actualUid);
3841 }
3842
3843 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003844 public void testResolveNotificationUid_sameApp() throws Exception {
3845 ApplicationInfo info = new ApplicationInfo();
3846 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04003847 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003848
3849 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
3850
3851 assertEquals(info.uid, actualUid);
3852 }
3853
3854 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003855 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003856 ApplicationInfo info = new ApplicationInfo();
3857 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003858 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003859
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003860 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
3861
3862 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003863 }
3864
3865 @Test
3866 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
3867 ApplicationInfo info = new ApplicationInfo();
3868 info.uid = 1356347;
3869 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
3870
3871 try {
3872 mService.resolveNotificationUid("caller", "caller", 9, 0);
3873 fail("Incorrect uid didn't throw security exception");
3874 } catch (SecurityException e) {
3875 // yay
3876 }
3877 }
3878
3879 @Test
3880 public void testResolveNotificationUid_delegateAllowed() throws Exception {
3881 int expectedUid = 123;
3882
3883 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3884 mService.setPreferencesHelper(mPreferencesHelper);
3885 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
3886 .thenReturn(true);
3887
3888 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
3889 }
3890
3891 @Test
3892 public void testResolveNotificationUid_androidAllowed() throws Exception {
3893 int expectedUid = 123;
3894
3895 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3896 // no delegate
3897
3898 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
3899 }
3900
3901 @Test
3902 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
3903 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
3904 // no delegate
3905
3906 try {
3907 mService.resolveNotificationUid("caller", "target", 9, 0);
3908 fail("Incorrect uid didn't throw security exception");
3909 } catch (SecurityException e) {
3910 // yay
3911 }
3912 }
Julia Reynolds564273f2018-09-13 15:53:11 -04003913
3914 @Test
3915 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
3916 Notification n = new Notification.Builder(mContext, "").build();
3917 n.flags |= FLAG_FOREGROUND_SERVICE;
3918
3919 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3920 n, new UserHandle(mUid), null, 0);
3921 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3922
3923 mService.addEnqueuedNotification(r);
3924
3925 mInternalService.removeForegroundServiceFlagFromNotification(
3926 PKG, r.sbn.getId(), r.sbn.getUserId());
3927
3928 waitForIdle();
3929
3930 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
3931 }
3932
3933 @Test
3934 public void testRemoveForegroundServiceFlagFromNotification_posted() {
3935 Notification n = new Notification.Builder(mContext, "").build();
3936 n.flags |= FLAG_FOREGROUND_SERVICE;
3937
3938 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3939 n, new UserHandle(mUid), null, 0);
3940 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3941
3942 mService.addNotification(r);
3943
3944 mInternalService.removeForegroundServiceFlagFromNotification(
3945 PKG, r.sbn.getId(), r.sbn.getUserId());
3946
3947 waitForIdle();
3948
3949 ArgumentCaptor<NotificationRecord> captor =
3950 ArgumentCaptor.forClass(NotificationRecord.class);
3951 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
3952
3953 assertEquals(0, captor.getValue().getNotification().flags);
3954 }
Beverly58b24532018-10-02 09:08:23 -04003955
3956 @Test
3957 public void testAllowForegroundToasts() throws Exception {
3958 final String testPackage = "testPackageName";
3959 assertEquals(0, mService.mToastQueue.size());
3960 mService.isSystemUid = false;
3961
3962 // package is not suspended
3963 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
3964 .thenReturn(false);
3965
3966 // notifications from this package are blocked by the user
3967 mService.setPreferencesHelper(mPreferencesHelper);
3968 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
3969
3970 // this app is in the foreground
3971 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
3972
3973 // enqueue toast -> toast should still enqueue
3974 ((INotificationManager)mService.mService).enqueueToast(testPackage,
3975 new TestableToastCallback(), 2000, 0);
3976 assertEquals(1, mService.mToastQueue.size());
3977 }
3978
3979 @Test
3980 public void testDisallowToastsFromSuspendedPackages() throws Exception {
3981 final String testPackage = "testPackageName";
3982 assertEquals(0, mService.mToastQueue.size());
3983 mService.isSystemUid = false;
3984
3985 // package is suspended
3986 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
3987 .thenReturn(true);
3988
3989 // notifications from this package are NOT blocked by the user
3990 mService.setPreferencesHelper(mPreferencesHelper);
3991 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
3992
3993 // enqueue toast -> no toasts enqueued
3994 ((INotificationManager)mService.mService).enqueueToast(testPackage,
3995 new TestableToastCallback(), 2000, 0);
3996 assertEquals(0, mService.mToastQueue.size());
3997 }
3998
3999 @Test
4000 public void testDisallowToastsFromBlockedApps() throws Exception {
4001 final String testPackage = "testPackageName";
4002 assertEquals(0, mService.mToastQueue.size());
4003 mService.isSystemUid = false;
4004
4005 // package is not suspended
4006 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4007 .thenReturn(false);
4008
4009 // notifications from this package are blocked by the user
4010 mService.setPreferencesHelper(mPreferencesHelper);
4011 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4012
4013 // this app is NOT in the foreground
4014 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4015
4016 // enqueue toast -> no toasts enqueued
4017 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4018 new TestableToastCallback(), 2000, 0);
4019 assertEquals(0, mService.mToastQueue.size());
4020 }
4021
4022 @Test
4023 public void testAlwaysAllowSystemToasts() throws Exception {
4024 final String testPackage = "testPackageName";
4025 assertEquals(0, mService.mToastQueue.size());
4026 mService.isSystemUid = true;
4027
4028 // package is suspended
4029 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4030 .thenReturn(true);
4031
4032 // notifications from this package ARE blocked by the user
4033 mService.setPreferencesHelper(mPreferencesHelper);
4034 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4035
4036 // this app is NOT in the foreground
4037 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4038
4039 // enqueue toast -> system toast can still be enqueued
4040 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4041 new TestableToastCallback(), 2000, 0);
4042 assertEquals(1, mService.mToastQueue.size());
4043 }
Tony Mak29996702018-11-26 16:23:34 +00004044
4045 @Test
4046 public void testOnNotificationSmartReplySent() {
4047 final int replyIndex = 2;
4048 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004049 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004050 final boolean generatedByAssistant = true;
4051
4052 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004053 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004054 mService.addNotification(r);
4055
4056 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004057 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4058 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004059 verify(mAssistants).notifyAssistantSuggestedReplySent(
4060 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4061 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004062
4063 @Test
4064 public void testOnNotificationActionClick() {
4065 final int actionIndex = 2;
4066 final Notification.Action action =
4067 new Notification.Action.Builder(null, "text", null).build();
4068 final boolean generatedByAssistant = false;
4069
4070 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4071 mService.addNotification(r);
4072
4073 NotificationVisibility notificationVisibility =
4074 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4075 mService.mNotificationDelegate.onNotificationActionClick(
4076 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4077 generatedByAssistant);
4078 verify(mAssistants).notifyAssistantActionClicked(
4079 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4080 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004081
4082 @Test
4083 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4084 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4085 mService.addNotification(r);
4086
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004087 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4088 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004089 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4090 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4091 };
4092 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4093 new NotificationVisibility[0]);
4094
4095 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4096 }
4097
4098 @Test
4099 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4100 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4101 mService.addNotification(r);
4102
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004103 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4104 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004105
4106 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4107 }
4108
4109 @Test
4110 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4111 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4112 mService.addNotification(r);
4113
Julia Reynolds95334132018-12-19 11:15:35 -05004114 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004115 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4116 };
4117 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4118 new NotificationVisibility[0]);
4119
4120 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4121 }
Julia Reynolds95334132018-12-19 11:15:35 -05004122
4123 public void testReportSeen_delegated() {
4124 Notification.Builder nb =
4125 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4126 .setContentTitle("foo")
4127 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4128
4129 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4130 nb.build(), new UserHandle(mUid), null, 0);
4131 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4132
4133 mService.reportSeen(r);
4134 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4135
4136 }
4137
4138 @Test
4139 public void testReportSeen_notDelegated() {
4140 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4141
4142 mService.reportSeen(r);
4143 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4144 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004145
4146 @Test
4147 public void testNotificationStats_notificationError() {
4148 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4149 mService.addNotification(r);
4150
4151 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4152 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4153 new UserHandle(mUid), null, 0);
4154 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4155 mService.addEnqueuedNotification(update);
4156 assertNull(update.sbn.getNotification().getSmallIcon());
4157
4158 NotificationManagerService.PostNotificationRunnable runnable =
4159 mService.new PostNotificationRunnable(update.getKey());
4160 runnable.run();
4161 waitForIdle();
4162
4163 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4164 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4165 assertNotNull(captor.getValue());
4166 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004167
4168 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004169 public void testCanNotifyAsUser_crossUser() throws Exception {
4170 // same user no problem
4171 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4172
4173 // cross user, no permission, problem
4174 try {
4175 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4176 fail("Should not be callable cross user without cross user permission");
4177 } catch (SecurityException e) {
4178 // good
4179 }
4180
4181 // cross user, with permission, no problem
4182 TestablePermissions perms = mContext.getTestablePermissions();
4183 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4184 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4185 }
4186
4187 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004188 public void testgetNotificationChannels_crossUser() throws Exception {
4189 // same user no problem
4190 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4191
4192 // cross user, no permission, problem
4193 try {
4194 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4195 fail("Should not be callable cross user without cross user permission");
4196 } catch (SecurityException e) {
4197 // good
4198 }
4199
4200 // cross user, with permission, no problem
4201 TestablePermissions perms = mContext.getTestablePermissions();
4202 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4203 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4204 }
4205
4206 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004207 public void setDefaultAssistantForUser_fromConfigXml() {
4208 clearDeviceConfig();
4209 ComponentName xmlConfig = new ComponentName("config", "xml");
4210 when(mResources
4211 .getString(
4212 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4213 .thenReturn(xmlConfig.flattenToString());
4214 when(mContext.getResources()).thenReturn(mResources);
4215 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4216 .thenReturn(Collections.singleton(xmlConfig));
4217 mService.setNotificationAssistantAccessGrantedCallback(
4218 mNotificationAssistantAccessGrantedCallback);
4219
4220 mService.setDefaultAssistantForUser(0);
4221
4222 verify(mNotificationAssistantAccessGrantedCallback)
4223 .onGranted(eq(xmlConfig), eq(0), eq(true));
4224 }
4225
4226 @Test
4227 public void setDefaultAssistantForUser_fromDeviceConfig() {
4228 ComponentName xmlConfig = new ComponentName("xml", "config");
4229 ComponentName deviceConfig = new ComponentName("device", "config");
4230 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4231 when(mResources
4232 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4233 .thenReturn(xmlConfig.flattenToString());
4234 when(mContext.getResources()).thenReturn(mResources);
4235 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4236 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
4237 mService.setNotificationAssistantAccessGrantedCallback(
4238 mNotificationAssistantAccessGrantedCallback);
4239
4240 mService.setDefaultAssistantForUser(0);
4241
4242 verify(mNotificationAssistantAccessGrantedCallback)
4243 .onGranted(eq(deviceConfig), eq(0), eq(true));
4244 }
4245
4246 @Test
4247 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4248 ComponentName xmlConfig = new ComponentName("xml", "config");
4249 ComponentName deviceConfig = new ComponentName("device", "config");
4250 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4251 when(mResources
4252 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4253 .thenReturn(xmlConfig.flattenToString());
4254 when(mContext.getResources()).thenReturn(mResources);
4255 // Only xmlConfig is valid, deviceConfig is not.
4256 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4257 .thenReturn(Collections.singleton(xmlConfig));
4258 mService.setNotificationAssistantAccessGrantedCallback(
4259 mNotificationAssistantAccessGrantedCallback);
4260
4261 mService.setDefaultAssistantForUser(0);
4262
4263 verify(mNotificationAssistantAccessGrantedCallback)
4264 .onGranted(eq(xmlConfig), eq(0), eq(true));
4265 }
4266
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004267 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004268 public void testFlagBubble() throws RemoteException {
4269 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004270 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004271
4272 // Notif with bubble metadata but not our other misc requirements
4273 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4274 null /* tvExtender */, true /* isBubble */);
4275
4276 // Say we're foreground
4277 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4278 IMPORTANCE_FOREGROUND);
4279
4280 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4281 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4282 waitForIdle();
4283
4284 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4285 assertEquals(1, notifs.length);
4286 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4287 assertTrue(mService.getNotificationRecord(
4288 nr.sbn.getKey()).getNotification().isBubbleNotification());
4289 }
4290
4291 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004292 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4293 // Bubbles are allowed!
4294 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4295
4296 // Notif with bubble metadata but not our other misc requirements
4297 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4298 null /* tvExtender */, true /* isBubble */);
4299
4300 // Say we're foreground
4301 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4302 IMPORTANCE_FOREGROUND);
4303
4304 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4305 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4306 waitForIdle();
4307
4308 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4309 assertEquals(1, notifs.length);
4310 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4311 assertFalse(mService.getNotificationRecord(
4312 nr.sbn.getKey()).getNotification().isBubbleNotification());
4313 }
4314
4315 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004316 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004317 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004318 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004319
Mady Mellorbe797962019-04-01 16:04:24 -07004320 // Notif with bubble metadata but not our other misc requirements
4321 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4322 null /* tvExtender */, true /* isBubble */);
4323
4324 // Say we're foreground
4325 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4326 IMPORTANCE_FOREGROUND);
4327
4328 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4329 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4330 waitForIdle();
4331
4332 // yes allowed, yes foreground, yes bubble
4333 assertTrue(mService.getNotificationRecord(
4334 nr.sbn.getKey()).getNotification().isBubbleNotification());
4335 }
4336
4337 @Test
4338 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4339 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004340 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004341
4342 // Notif with bubble metadata but not our other misc requirements
4343 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4344 null /* tvExtender */, true /* isBubble */);
4345
4346 // Make sure we're NOT foreground
4347 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4348 IMPORTANCE_VISIBLE);
4349
4350 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4351 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4352 waitForIdle();
4353
4354 // yes allowed but NOT foreground, no bubble
4355 assertFalse(mService.getNotificationRecord(
4356 nr.sbn.getKey()).getNotification().isBubbleNotification());
4357 }
4358
4359 @Test
4360 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4361 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004362 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004363
4364 // Notif with bubble metadata but not our other misc requirements
4365 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4366 null /* tvExtender */, true /* isBubble */);
4367
4368 // Send notif when we're foreground
4369 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4370 IMPORTANCE_FOREGROUND);
4371 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4372 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4373 waitForIdle();
4374
4375 // yes allowed, yes foreground, yes bubble
4376 assertTrue(mService.getNotificationRecord(
4377 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4378
4379 // Send a new update when we're not foreground
4380 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4381 null /* tvExtender */, true /* isBubble */);
4382
4383 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4384 IMPORTANCE_VISIBLE);
4385 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4386 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4387 waitForIdle();
4388
4389 // yes allowed, previously foreground / flagged, yes bubble
4390 assertTrue(mService.getNotificationRecord(
4391 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4392
4393 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4394 assertEquals(1, notifs2.length);
4395 assertEquals(1, mService.getNotificationRecordCount());
4396 }
4397
4398 @Test
4399 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4400 throws RemoteException {
4401 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004402 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004403
4404 // Notif with bubble metadata but not our other misc requirements
4405 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4406 null /* tvExtender */, true /* isBubble */);
4407
4408 // Send notif when we're foreground
4409 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4410 IMPORTANCE_FOREGROUND);
4411 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4412 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4413 waitForIdle();
4414
4415 // yes allowed, yes foreground, yes bubble
4416 assertTrue(mService.getNotificationRecord(
4417 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4418
4419 // Remove the bubble
4420 mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(),
4421 nr1.sbn.getUserId());
4422 waitForIdle();
4423
4424 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4425 assertEquals(0, notifs.length);
4426 assertEquals(0, mService.getNotificationRecordCount());
4427
4428 // Send a new update when we're not foreground
4429 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4430 null /* tvExtender */, true /* isBubble */);
4431
4432 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4433 IMPORTANCE_VISIBLE);
4434 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4435 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4436 waitForIdle();
4437
4438 // yes allowed, but was removed & no foreground, so no bubble
4439 assertFalse(mService.getNotificationRecord(
4440 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4441
4442 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4443 assertEquals(1, notifs2.length);
4444 assertEquals(1, mService.getNotificationRecordCount());
4445 }
4446
4447 @Test
4448 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4449 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004450 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004451
4452 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004453 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004454 // Give it a person
4455 Person person = new Person.Builder()
4456 .setName("bubblebot")
4457 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004458 // It needs remote input to be bubble-able
4459 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4460 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4461 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4462 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4463 inputIntent).addRemoteInput(remoteInput)
4464 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004465 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004466 Notification.Builder nb = new Notification.Builder(mContext,
4467 mTestNotificationChannel.getId())
4468 .setContentTitle("foo")
4469 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004470 .setStyle(new Notification.MessagingStyle(person)
4471 .setConversationTitle("Bubble Chat")
4472 .addMessage("Hello?",
4473 SystemClock.currentThreadTimeMillis() - 300000, person)
4474 .addMessage("Is it me you're looking for?",
4475 SystemClock.currentThreadTimeMillis(), person)
4476 )
Mady Mellora10448e2019-04-26 13:50:58 -07004477 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -07004478 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4479
4480 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4481 nb.build(), new UserHandle(mUid), null, 0);
4482 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4483
4484 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4485 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4486 waitForIdle();
4487
4488 // yes allowed, yes messaging, yes bubble
4489 assertTrue(mService.getNotificationRecord(
4490 sbn.getKey()).getNotification().isBubbleNotification());
4491 }
4492
4493 @Test
4494 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4495 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004496 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004497
4498 // Give it bubble metadata
4499 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4500 // Give it a person
4501 Person person = new Person.Builder()
4502 .setName("bubblebot")
4503 .build();
4504 // Make it a phone call
4505 Notification.Builder nb = new Notification.Builder(mContext,
4506 mTestNotificationChannel.getId())
4507 .setCategory(CATEGORY_CALL)
4508 .addPerson(person)
4509 .setContentTitle("foo")
4510 .setBubbleMetadata(data)
4511 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4512
4513 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4514 nb.build(), new UserHandle(mUid), null, 0);
4515 // Make sure it has foreground service
4516 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4517 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4518
4519 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4520 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4521 waitForIdle();
4522
4523 // yes phone call, yes person, yes foreground service, yes bubble
4524 assertTrue(mService.getNotificationRecord(
4525 sbn.getKey()).getNotification().isBubbleNotification());
4526 }
4527
4528 @Test
4529 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4530 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004531 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004532
4533 // Give it bubble metadata
4534 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4535 // Give it a person
4536 Person person = new Person.Builder()
4537 .setName("bubblebot")
4538 .build();
4539 // Make it a phone call
4540 Notification.Builder nb = new Notification.Builder(mContext,
4541 mTestNotificationChannel.getId())
4542 .setCategory(CATEGORY_CALL)
4543 .addPerson(person)
4544 .setContentTitle("foo")
4545 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004546 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4547
4548 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4549 nb.build(), new UserHandle(mUid), null, 0);
4550 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4551
4552 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4553 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4554 waitForIdle();
4555
Mady Mellorbe797962019-04-01 16:04:24 -07004556 // yes phone call, yes person, NO foreground service, no bubble
4557 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004558 sbn.getKey()).getNotification().isBubbleNotification());
4559 }
4560
4561 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004562 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4563 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004564 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004565
4566 // Give it bubble metadata
4567 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4568 // Make it a phone call
4569 Notification.Builder nb = new Notification.Builder(mContext,
4570 mTestNotificationChannel.getId())
4571 .setCategory(CATEGORY_CALL)
4572 .setContentTitle("foo")
4573 .setBubbleMetadata(data)
4574 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4575
4576 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4577 nb.build(), new UserHandle(mUid), null, 0);
4578 // Make sure it has foreground service
4579 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4580 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4581
4582 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4583 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4584 waitForIdle();
4585
4586 // yes phone call, yes foreground service, BUT NO person, no bubble
4587 assertFalse(mService.getNotificationRecord(
4588 sbn.getKey()).getNotification().isBubbleNotification());
4589 }
4590
4591 @Test
4592 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4593 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004594 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004595
4596 // Give it bubble metadata
4597 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4598 // Give it a person
4599 Person person = new Person.Builder()
4600 .setName("bubblebot")
4601 .build();
4602 // No category
4603 Notification.Builder nb = new Notification.Builder(mContext,
4604 mTestNotificationChannel.getId())
4605 .addPerson(person)
4606 .setContentTitle("foo")
4607 .setBubbleMetadata(data)
4608 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4609
4610 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4611 nb.build(), new UserHandle(mUid), null, 0);
4612 // Make sure it has foreground service
4613 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4614 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4615
4616 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4617 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4618 waitForIdle();
4619
4620 // yes person, yes foreground service, BUT NO call, no bubble
4621 assertFalse(mService.getNotificationRecord(
4622 sbn.getKey()).getNotification().isBubbleNotification());
4623 }
4624
4625 @Test
4626 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004627 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004628 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004629
Mady Mellorbe797962019-04-01 16:04:24 -07004630 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004631 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004632 // Give it a person
4633 Person person = new Person.Builder()
4634 .setName("bubblebot")
4635 .build();
4636 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004637 Notification.Builder nb = new Notification.Builder(mContext,
4638 mTestNotificationChannel.getId())
4639 .setContentTitle("foo")
4640 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004641 .setStyle(new Notification.MessagingStyle(person)
4642 .setConversationTitle("Bubble Chat")
4643 .addMessage("Hello?",
4644 SystemClock.currentThreadTimeMillis() - 300000, person)
4645 .addMessage("Is it me you're looking for?",
4646 SystemClock.currentThreadTimeMillis(), person)
4647 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004648 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4649
4650 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4651 nb.build(), new UserHandle(mUid), null, 0);
4652 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4653
4654 // Post the notification
4655 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4656 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4657 waitForIdle();
4658
4659 // not allowed, no bubble
4660 assertFalse(mService.getNotificationRecord(
4661 sbn.getKey()).getNotification().isBubbleNotification());
4662 }
4663
4664 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004665 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004666 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004667 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004668
4669 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07004670 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004671
4672 // Post the notification
Mady Mellorbe797962019-04-01 16:04:24 -07004673 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004674 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4675 waitForIdle();
4676
4677 // no bubble metadata, no bubble
4678 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07004679 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004680 }
4681
4682 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004683 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004684 // Bubbles are allowed except on this channel
4685 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004686
Mady Mellorbe797962019-04-01 16:04:24 -07004687 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004688 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004689 // Give it a person
4690 Person person = new Person.Builder()
4691 .setName("bubblebot")
4692 .build();
4693 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004694 Notification.Builder nb = new Notification.Builder(mContext,
4695 mTestNotificationChannel.getId())
4696 .setContentTitle("foo")
4697 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004698 .setStyle(new Notification.MessagingStyle(person)
4699 .setConversationTitle("Bubble Chat")
4700 .addMessage("Hello?",
4701 SystemClock.currentThreadTimeMillis() - 300000, person)
4702 .addMessage("Is it me you're looking for?",
4703 SystemClock.currentThreadTimeMillis(), person)
4704 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004705 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4706
4707 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4708 nb.build(), new UserHandle(mUid), null, 0);
4709 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4710
4711 // Post the notification
4712 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4713 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4714 waitForIdle();
4715
4716 // channel not allowed, no bubble
4717 assertFalse(mService.getNotificationRecord(
4718 sbn.getKey()).getNotification().isBubbleNotification());
4719 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004720
Mady Mellor49b1bf12019-03-29 12:00:02 -07004721 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004722 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004723 // Bubbles are not allowed!
4724 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004725
4726 // Give it bubble metadata
4727 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4728 // Give it a person
4729 Person person = new Person.Builder()
4730 .setName("bubblebot")
4731 .build();
4732 // Make it a phone call
4733 Notification.Builder nb = new Notification.Builder(mContext,
4734 mTestNotificationChannel.getId())
4735 .setCategory(CATEGORY_CALL)
4736 .addPerson(person)
4737 .setContentTitle("foo")
4738 .setBubbleMetadata(data)
4739 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4740
4741 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4742 nb.build(), new UserHandle(mUid), null, 0);
4743 // Make sure it has foreground service
4744 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4745 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4746
4747 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4748 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4749 waitForIdle();
4750
4751 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
4752 assertFalse(mService.getNotificationRecord(
4753 sbn.getKey()).getNotification().isBubbleNotification());
4754 }
4755
4756 @Test
4757 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004758 // Bubbles are allowed, but not on channel.
4759 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004760
4761 // Give it bubble metadata
4762 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4763 // Give it a person
4764 Person person = new Person.Builder()
4765 .setName("bubblebot")
4766 .build();
4767 // Make it a phone call
4768 Notification.Builder nb = new Notification.Builder(mContext,
4769 mTestNotificationChannel.getId())
4770 .setCategory(CATEGORY_CALL)
4771 .addPerson(person)
4772 .setContentTitle("foo")
4773 .setBubbleMetadata(data)
4774 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4775
4776 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4777 nb.build(), new UserHandle(mUid), null, 0);
4778 // Make sure it has foreground service
4779 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4780 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4781
4782 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4783 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4784 waitForIdle();
4785
4786 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
4787 assertFalse(mService.getNotificationRecord(
4788 sbn.getKey()).getNotification().isBubbleNotification());
4789 }
4790
4791 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07004792 public void testCancelAllNotifications_cancelsBubble() throws Exception {
4793 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4794 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
4795 mService.addNotification(nr);
4796
4797 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
4798 waitForIdle();
4799
4800 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4801 assertEquals(0, notifs.length);
4802 assertEquals(0, mService.getNotificationRecordCount());
4803 }
4804
4805 @Test
4806 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
4807 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4808 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4809
4810 // Post the notification
4811 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4812 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
4813 waitForIdle();
4814
4815 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4816 assertEquals(1, notifs.length);
4817 assertEquals(1, mService.getNotificationRecordCount());
4818
4819 mBinderService.cancelNotificationWithTag(PKG, null, nrBubble.sbn.getId(),
4820 nrBubble.sbn.getUserId());
4821 waitForIdle();
4822
4823 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4824 assertEquals(0, notifs2.length);
4825 assertEquals(0, mService.getNotificationRecordCount());
4826 }
4827
4828 @Test
4829 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
4830 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4831 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4832 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4833
4834 mService.addNotification(nrNormal);
4835 mService.addNotification(nrBubble);
4836
4837 mService.getBinderService().cancelNotificationsFromListener(null, null);
4838 waitForIdle();
4839
4840 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4841 assertEquals(1, notifs.length);
4842 assertEquals(1, mService.getNotificationRecordCount());
4843 }
4844
4845 @Test
4846 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
4847 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4848 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4849 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4850
4851 mService.addNotification(nrNormal);
4852 mService.addNotification(nrBubble);
4853
4854 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
4855 mService.getBinderService().cancelNotificationsFromListener(null, keys);
4856 waitForIdle();
4857
4858 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4859 assertEquals(1, notifs.length);
4860 assertEquals(1, mService.getNotificationRecordCount());
4861 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004862
Julia Reynolds4214da92019-04-10 15:04:06 -04004863 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04004864 public void testGetAllowedAssistantAdjustments() throws Exception {
4865 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004866 assertNotNull(capabilities);
4867
4868 for (int i = capabilities.size() - 1; i >= 0; i--) {
4869 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04004870 mBinderService.disallowAssistantAdjustment(capability);
4871 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
4872 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004873 assertNotNull(currentCapabilities);
4874 assertFalse(currentCapabilities.contains(capability));
4875 }
4876 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004877
Julia Reynolds4214da92019-04-10 15:04:06 -04004878 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004879 public void testAdjustRestrictedKey() throws Exception {
4880 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04004881 mService.addNotification(r);
4882 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004883
4884 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
4885 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
4886
4887 Bundle signals = new Bundle();
4888 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
4889 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
4890 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
4891 "", r.getUser().getIdentifier());
4892
4893 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
4894 r.applyAdjustments();
4895
4896 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
4897 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
4898 }
Julia Reynolds657d1642019-03-27 12:15:57 -04004899
Julia Reynolds4214da92019-04-10 15:04:06 -04004900 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004901 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04004902 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
4903 .thenReturn(true);
4904 mService.setZenHelper(mock(ZenModeHelper.class));
4905 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004906 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
4907 boolean isEnabled = true;
4908 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4909 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4910
4911 try {
4912 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04004913 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004914 } catch (IllegalArgumentException e) {
4915 // yay
4916 }
4917
4918 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4919 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
4920 mBinderService.addAutomaticZenRule(rule);
4921
4922 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4923 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4924 mBinderService.addAutomaticZenRule(rule);
4925 }
4926
Julia Reynolds4214da92019-04-10 15:04:06 -04004927 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04004928 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
4929 try {
4930 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
4931 mUid + UserHandle.PER_USER_RANGE);
4932 fail("Cannot call cross user without permission");
4933 } catch (SecurityException e) {
4934 // pass
4935 }
4936
4937 // cross user, with permission, no problem
4938 TestablePermissions perms = mContext.getTestablePermissions();
4939 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4940 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
4941 mUid + UserHandle.PER_USER_RANGE);
4942 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04004943
Julia Reynolds4214da92019-04-10 15:04:06 -04004944 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04004945 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
4946 try {
4947 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
4948 mUid + UserHandle.PER_USER_RANGE);
4949 fail("Cannot call cross user without permission");
4950 } catch (SecurityException e) {
4951 // pass
4952 }
4953
4954 // cross user, with permission, no problem
4955 TestablePermissions perms = mContext.getTestablePermissions();
4956 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4957 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
4958 mUid + UserHandle.PER_USER_RANGE);
4959 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07004960
4961 @Test
4962 public void testNotificationBubbleChanged_false() throws Exception {
4963 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004964 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07004965
4966 // Notif with bubble metadata but not our other misc requirements
4967 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4968 null /* tvExtender */, true /* isBubble */);
4969
4970 // Say we're foreground
4971 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4972 IMPORTANCE_FOREGROUND);
4973
4974 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4975 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4976 waitForIdle();
4977
Mady Mellor66efd5e2019-05-15 13:38:11 -07004978 // Reset as this is called when the notif is first sent
4979 reset(mListeners);
4980
Mady Mellora54e9fa2019-04-18 13:26:18 -07004981 // First we were a bubble
4982 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
4983 assertEquals(1, notifsBefore.length);
4984 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
4985
4986 // Notify we're not a bubble
4987 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
4988 waitForIdle();
4989
Mady Mellor3a0a1b42019-05-23 06:40:21 -07004990 // Make sure we are not a bubble
4991 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
4992 assertEquals(1, notifsAfter.length);
4993 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07004994 }
4995
4996 @Test
4997 public void testNotificationBubbleChanged_true() throws Exception {
4998 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004999 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005000
5001 // Plain notification that has bubble metadata
5002 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5003 null /* tvExtender */, true /* isBubble */);
5004 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5005 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5006 waitForIdle();
5007
5008 // Would be a normal notification because wouldn't have met requirements to bubble
5009 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5010 assertEquals(1, notifsBefore.length);
5011 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5012
5013 // Make the package foreground so that we're allowed to be a bubble
5014 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5015 IMPORTANCE_FOREGROUND);
5016
Mady Mellor66efd5e2019-05-15 13:38:11 -07005017 // Reset as this is called when the notif is first sent
5018 reset(mListeners);
5019
Mady Mellora54e9fa2019-04-18 13:26:18 -07005020 // Notify we are now a bubble
5021 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5022 waitForIdle();
5023
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005024 // Make sure we are a bubble
5025 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5026 assertEquals(1, notifsAfter.length);
5027 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005028 }
5029
5030 @Test
5031 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5032 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005033 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005034
5035 // Notif that is not a bubble
5036 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5037 null /* tvExtender */, true /* isBubble */);
5038 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5039 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5040 waitForIdle();
5041
Mady Mellor66efd5e2019-05-15 13:38:11 -07005042 // Reset as this is called when the notif is first sent
5043 reset(mListeners);
5044
Mady Mellora54e9fa2019-04-18 13:26:18 -07005045 // Would be a normal notification because wouldn't have met requirements to bubble
5046 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5047 assertEquals(1, notifsBefore.length);
5048 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5049
5050 // Notify we are now a bubble
5051 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5052 waitForIdle();
5053
5054 // We still wouldn't be a bubble because the notification didn't meet requirements
5055 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5056 assertEquals(1, notifsAfter.length);
5057 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5058 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005059
5060 @Test
5061 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5062 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005063 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005064
5065 // Plain notification that has bubble metadata
5066 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5067 null /* tvExtender */, true /* isBubble */);
5068 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5069 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5070 waitForIdle();
5071
5072 // Would be a normal notification because wouldn't have met requirements to bubble
5073 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5074 assertEquals(1, notifsBefore.length);
5075 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5076
5077 // Make the package foreground so that we're allowed to be a bubble
5078 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5079 IMPORTANCE_FOREGROUND);
5080
5081 // And we are low ram
5082 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5083
5084 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5085 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5086 assertEquals(1, notifsAfter.length);
5087 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005088 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005089}