blob: 3ac7a79a163010b40435adbba879281b3464ce32 [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 Reynolds469144c2019-06-21 14:30:28 -0400134import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400135import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400136
Mady Mellor49b1bf12019-03-29 12:00:02 -0700137import androidx.annotation.Nullable;
138import androidx.test.InstrumentationRegistry;
139
Kristian Monsen05f34792018-04-09 10:27:16 +0200140import com.android.internal.R;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000141import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Julia Reynolds503ed942017-10-04 16:04:56 -0400142import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400143import com.android.internal.util.FastXmlSerializer;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700144import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400145import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500146import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400147import com.android.server.lights.Light;
148import com.android.server.lights.LightsManager;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400149import com.android.server.notification.NotificationManagerService.NotificationAssistants;
150import com.android.server.notification.NotificationManagerService.NotificationListeners;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700151import com.android.server.uri.UriGrantsManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400152import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400153
154import org.junit.After;
155import org.junit.Before;
156import org.junit.Test;
157import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500158import org.mockito.ArgumentCaptor;
159import org.mockito.Mock;
160import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400161import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400162import org.xmlpull.v1.XmlPullParser;
163import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500164
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400165import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400166import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400167import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400168import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400169import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400170import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400171import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500172import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000173import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400174import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400175import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200176import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500177
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400178
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400179@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400180@RunWith(AndroidTestingRunner.class)
181@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500182public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500183 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000184
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400185 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500186 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500187 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400188 private NotificationManagerInternal mInternalService;
Julia Reynoldsda781472017-04-12 09:41:16 -0400189 @Mock
190 private IPackageManager mPackageManager;
191 @Mock
192 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400193 @Mock
194 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400195 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500196 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400197 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400198 @Mock
199 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400200 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400201 AtomicFile mPolicyFile;
202 File mFile;
203 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400204 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400205 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400206 private UsageStatsManagerInternal mAppUsageStats;
207 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400208 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400209 @Mock
210 ActivityManager mActivityManager;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400211 NotificationManagerService.WorkerHandler mHandler;
Kristian Monsen05f34792018-04-09 10:27:16 +0200212 @Mock
213 Resources mResources;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400214
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500215 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500216 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000217
218 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
219
Julia Reynoldsda781472017-04-12 09:41:16 -0400220 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400221 private NotificationListeners mListeners;
222 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400223 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400224 private ManagedServices.ManagedServiceInfo mListener;
225 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400226 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400227 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400228 @Mock
229 IBinder mPermOwner;
230 @Mock
231 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700232 @Mock
233 IUriGrantsManager mUgm;
234 @Mock
235 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400236 @Mock
237 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000238 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000239 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
240 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400241 @Mock
242 UserManager mUm;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500243
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400244 // Use a Testable subclass so we can simulate calls from the system without failing.
245 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500246 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700247 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000248 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000249 @Nullable
250 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500251
Julia Reynolds0c245002019-03-27 16:10:11 -0400252 TestableNotificationManagerService(Context context) {
Amith Yamasani803eab692017-11-09 17:47:04 -0800253 super(context);
254 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400255
256 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400257 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500258 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700259 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400260 }
261
262 @Override
263 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500264 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700265 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400266 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400267
268 @Override
269 protected ICompanionDeviceManager getCompanionManager() {
270 return null;
271 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800272
273 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800274 protected void reportUserInteraction(NotificationRecord r) {
275 return;
276 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500277
278 @Override
279 protected void handleSavePolicyFile() {
280 return;
281 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000282
283 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000284 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
285 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000286 countLogSmartSuggestionsVisible++;
287 }
288
Annie Meng8b646fd2019-02-01 18:46:42 +0000289 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000290 protected void setNotificationAssistantAccessGrantedForUserInternal(
291 ComponentName assistant, int userId, boolean granted) {
292 if (mNotificationAssistantAccessGrantedCallback != null) {
293 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
294 return;
295 }
296 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
297 }
298
299 private void setNotificationAssistantAccessGrantedCallback(
300 @Nullable NotificationAssistantAccessGrantedCallback callback) {
301 this.mNotificationAssistantAccessGrantedCallback = callback;
302 }
303
304 interface NotificationAssistantAccessGrantedCallback {
305 void onGranted(ComponentName assistant, int userId, boolean granted);
306 }
307
Mady Mellorca0c24c2019-05-16 16:14:32 -0700308 @Override
309 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
310 String packageName) {
311 // Tests for this not being true are in CTS NotificationManagerTest
312 return true;
313 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400314 }
315
Beverly58b24532018-10-02 09:08:23 -0400316 private class TestableToastCallback extends ITransientNotification.Stub {
317 @Override
318 public void show(IBinder windowToken) {
319 }
320
321 @Override
322 public void hide() {
323 }
324 }
325
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500326 @Before
327 public void setUp() throws Exception {
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000328 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
329 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
330
Julia Reynoldsda781472017-04-12 09:41:16 -0400331 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400332
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700333 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
334 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400335 LocalServices.removeServiceForTest(WindowManagerInternal.class);
336 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700337
Julia Reynolds4afe2642019-05-01 08:42:24 -0400338 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
339
Julia Reynolds0c245002019-03-27 16:10:11 -0400340 mService = new TestableNotificationManagerService(mContext);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500341
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400342 // Use this testable looper.
343 mTestableLooper = TestableLooper.get(this);
Julia Reynolds503ed942017-10-04 16:04:56 -0400344 mHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500345 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400346 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400347
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400348 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400349 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
350 Object[] args = invocation.getArguments();
351 return getApplicationInfo((String) args[0], mUid);
352 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500353 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400354 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
355 Object[] args = invocation.getArguments();
356 return getApplicationInfo((String) args[0], mUid);
357 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400358 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500359 final LightsManager mockLightsManager = mock(LightsManager.class);
360 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400361 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400362 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700363 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400364 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400365 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400366 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500367
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400368 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400369 mFile = new File(mContext.getCacheDir(), "test.xml");
370 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400371 final String preupgradeXml = "<notification-policy></notification-policy>";
372 mPolicyFile = new AtomicFile(mFile);
373 FileOutputStream fos = mPolicyFile.startWrite();
374 fos.write(preupgradeXml.getBytes());
375 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400376
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400377 // Setup managed services
378 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400379 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400380 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
381 ManagedServices.Config listenerConfig = new ManagedServices.Config();
382 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
383 when(mListeners.getConfig()).thenReturn(listenerConfig);
384 ManagedServices.Config assistantConfig = new ManagedServices.Config();
385 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
386 when(mAssistants.getConfig()).thenReturn(assistantConfig);
387 ManagedServices.Config dndConfig = new ManagedServices.Config();
388 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
389 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
390
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400391 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
392
Julia Reynolds4afe2642019-05-01 08:42:24 -0400393 mService.init(mTestableLooper.getLooper(),
394 mPackageManager, mPackageManagerClient, mockLightsManager,
395 mListeners, mAssistants, mConditionProviders,
396 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
397 mGroupHelper, mAm, mAppUsageStats,
398 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
399 mAppOpsManager, mUm);
400 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
401
Julia Reynolds503ed942017-10-04 16:04:56 -0400402 mService.setAudioManager(mAudioManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500403
404 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400405 mBinderService = mService.getBinderService();
406 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500407
408 mBinderService.createNotificationChannels(
409 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400410 assertNotNull(mBinderService.getNotificationChannel(
411 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500412 }
413
Julia Reynoldsb852e562017-06-06 16:14:18 -0400414 @After
415 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400416 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000417 clearDeviceConfig();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000418 InstrumentationRegistry.getInstrumentation()
419 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400420 }
421
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400422 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
423 final ApplicationInfo applicationInfo = new ApplicationInfo();
424 applicationInfo.uid = uid;
425 switch (pkg) {
426 case PKG_N_MR1:
427 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
428 break;
429 case PKG_O:
430 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
431 break;
432 case PKG_P:
433 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
434 break;
435 default:
436 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
437 break;
438 }
439 return applicationInfo;
440 }
441
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500442 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400443 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500444 }
445
Mady Mellorc6820342019-05-20 12:04:36 -0700446 private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
447 boolean channelEnabled) {
448 mService.setPreferencesHelper(mPreferencesHelper);
449 when(mPreferencesHelper.bubblesEnabled(any())).thenReturn(globalEnabled);
450 when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
451 when(mPreferencesHelper.getNotificationChannel(
452 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
453 mTestNotificationChannel);
454 when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
455 mTestNotificationChannel.getImportance());
456 mTestNotificationChannel.setAllowBubbles(channelEnabled);
457 }
458
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500459 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
460 Notification.Builder nb = new Notification.Builder(mContext, "a")
461 .setContentTitle("foo")
462 .setSmallIcon(android.R.drawable.sym_def_app_icon);
463 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0,
464 nb.build(), new UserHandle(userId), null, postTime);
465 return sbn;
466 }
467
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400468 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
469 String groupKey, boolean isSummary) {
470 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
471 .setContentTitle("foo")
472 .setSmallIcon(android.R.drawable.sym_def_app_icon)
473 .setGroup(groupKey)
474 .setGroupSummary(isSummary);
475
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400476 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
477 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000478 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400479 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400480
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500481 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500482 return generateNotificationRecord(channel, null);
483 }
484
485 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
486 Notification.TvExtender extender) {
Mady Mellorbe797962019-04-01 16:04:24 -0700487 return generateNotificationRecord(channel, extender, false /* isBubble */);
488 }
489
490 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
491 Notification.TvExtender extender, boolean isBubble) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500492 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500493 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500494 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500495 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500496 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500497 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500498 if (extender != null) {
499 nb.extend(extender);
500 }
Mady Mellorbe797962019-04-01 16:04:24 -0700501 if (isBubble) {
502 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
503 }
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400504 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
505 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000506 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500507 }
508
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400509 private Map<String, Answer> getSignalExtractorSideEffects() {
510 Map<String, Answer> answers = new ArrayMap<>();
511
512 answers.put("override group key", invocationOnMock -> {
513 ((NotificationRecord) invocationOnMock.getArguments()[0])
514 .setOverrideGroupKey("bananas");
515 return null;
516 });
517 answers.put("override people", invocationOnMock -> {
518 ((NotificationRecord) invocationOnMock.getArguments()[0])
519 .setPeopleOverride(new ArrayList<>());
520 return null;
521 });
522 answers.put("snooze criteria", invocationOnMock -> {
523 ((NotificationRecord) invocationOnMock.getArguments()[0])
524 .setSnoozeCriteria(new ArrayList<>());
525 return null;
526 });
527 answers.put("notification channel", invocationOnMock -> {
528 ((NotificationRecord) invocationOnMock.getArguments()[0])
529 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
530 return null;
531 });
532 answers.put("badging", invocationOnMock -> {
533 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
534 r.setShowBadge(!r.canShowBadge());
535 return null;
536 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500537 answers.put("bubbles", invocationOnMock -> {
538 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
539 r.setAllowBubble(!r.canBubble());
540 return null;
541 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400542 answers.put("package visibility", invocationOnMock -> {
543 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
544 Notification.VISIBILITY_SECRET);
545 return null;
546 });
547
548 return answers;
549 }
550
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400551 private void clearDeviceConfig() {
552 DeviceConfig.resetToDefaults(
553 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
554 }
555
556 private void setDefaultAssistantInDeviceConfig(String componentName) {
557 DeviceConfig.setProperty(
558 DeviceConfig.NAMESPACE_SYSTEMUI,
559 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
560 componentName,
561 false);
562 }
563
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700564 private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() {
565 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
566 return new Notification.BubbleMetadata.Builder()
567 .setIntent(pi)
568 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
569 }
570
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500571 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500572 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500573 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500574 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400575 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500576 new ParceledListSlice(Arrays.asList(channel)));
577 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400578 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500579 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500580 }
581
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500582 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500583 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500584 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400585 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200586 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500587 fail("Exception should be thrown immediately.");
588 } catch (NullPointerException e) {
589 // pass
590 }
591 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500592
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500593 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500594 public void testCreateNotificationChannels_TwoChannels() throws Exception {
595 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500596 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500597 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500598 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400599 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500600 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400601 assertTrue(mBinderService.getNotificationChannel(
602 PKG, mContext.getUserId(), PKG, "id1") != null);
603 assertTrue(mBinderService.getNotificationChannel(
604 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500605 }
606
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500607 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400608 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
609 throws Exception {
610 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500611 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400612 mBinderService.createNotificationChannels(PKG,
613 new ParceledListSlice(Arrays.asList(channel)));
614
615 // Recreating the channel doesn't throw, but ignores importance.
616 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400617 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400618 mBinderService.createNotificationChannels(PKG,
619 new ParceledListSlice(Arrays.asList(dupeChannel)));
620 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400621 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500622 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400623 }
624
625 @Test
626 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
627 throws Exception {
628 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500629 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400630 mBinderService.createNotificationChannels(PKG,
631 new ParceledListSlice(Arrays.asList(channel)));
632
633 // Recreating with a lower importance is allowed to modify the channel.
634 final NotificationChannel dupeChannel =
635 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
636 mBinderService.createNotificationChannels(PKG,
637 new ParceledListSlice(Arrays.asList(dupeChannel)));
638 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400639 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400640 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
641 }
642
643 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400644 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
645 throws Exception {
646 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500647 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400648 mBinderService.createNotificationChannels(PKG,
649 new ParceledListSlice(Arrays.asList(channel)));
650
651 // The user modifies importance directly, can no longer be changed by the app.
652 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400653 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400654 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
655
656 // Recreating with a lower importance leaves channel unchanged.
657 final NotificationChannel dupeChannel =
658 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
659 mBinderService.createNotificationChannels(PKG,
660 new ParceledListSlice(Arrays.asList(dupeChannel)));
661 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400662 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400663 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400664 }
665
666 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500667 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
668 throws Exception {
669 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500670 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500671 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400672 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400673 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500674 new ParceledListSlice(Arrays.asList(channel1, channel2)));
675 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400676 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500677 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500678 }
679
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500680 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500681 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500682 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
683
684 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400685 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500686 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400687
688 // isBlocked is only used for user blocking, not app suspension
689 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500690 }
691
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500692 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500693 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500694 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
695
696 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400697 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500698 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400699 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400700 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400701
702 mBinderService.createNotificationChannels(
703 PKG, new ParceledListSlice(Arrays.asList(channel)));
704 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400705 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400706 sbn.getId(), sbn.getNotification(), sbn.getUserId());
707 waitForIdle();
708 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
709 }
710
711 @Test
712 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
713 throws Exception {
714 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
715
716 NotificationChannel channel = new NotificationChannel("blocked", "name",
717 NotificationManager.IMPORTANCE_NONE);
718 mBinderService.createNotificationChannels(
719 PKG, new ParceledListSlice(Arrays.asList(channel)));
720
721 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400722 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400723 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400724 sbn.getId(), sbn.getNotification(), sbn.getUserId());
725 waitForIdle();
726 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
727 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400728 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400729 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
730 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400731 }
732
733 @Test
734 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
735 throws Exception {
736 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
737
738 NotificationChannel channel =
739 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
740 mBinderService.createNotificationChannels(
741 PKG, new ParceledListSlice(Arrays.asList(channel)));
742
743 NotificationChannel update =
744 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
745 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
746 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400747 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
748 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400749
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700750 StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400751 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400752 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400753 sbn.getId(), sbn.getNotification(), sbn.getUserId());
754 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700755 // The first time a foreground service notification is shown, we allow the channel
756 // to be updated to allow it to be seen.
757 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
758 assertEquals(IMPORTANCE_LOW,
759 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400760 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
761 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400762 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700763 waitForIdle();
764
765 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
766 update.setFgServiceShown(true);
767 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
768 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400769 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
770 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700771
772 sbn = generateNotificationRecord(channel).sbn;
773 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400774 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700775 sbn.getId(), sbn.getNotification(), sbn.getUserId());
776 waitForIdle();
777 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400778 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400779 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400780 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
781 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500782 }
783
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500784 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -0400785 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
786 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400787 mService.setPreferencesHelper(mPreferencesHelper);
788 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400789
790 NotificationChannel channel = new NotificationChannel("id", "name",
791 NotificationManager.IMPORTANCE_HIGH);
792 channel.setGroup("something");
793 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400794 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -0400795 verify(mUsageStats, times(1)).registerBlocked(eq(r));
796 }
797
798 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -0400799 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500800 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
801
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400802 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -0400803
804 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400805 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds4da79702017-06-01 11:06:10 -0400806 sbn.getId(), sbn.getNotification(), sbn.getUserId());
807 waitForIdle();
808 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500809 }
810
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500811 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400812 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
813 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
814
815 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
816
817 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400818 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400819 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400820 sbn.getId(), sbn.getNotification(), sbn.getUserId());
821 waitForIdle();
822 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400823 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400824 }
825
Brad Stenning8c991ea2018-07-31 13:33:01 -0700826 /**
827 * Confirm the system user on automotive devices can use car categories
828 */
829 @Test
830 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
831 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
832 .thenReturn(true);
833 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
834 Notification.CATEGORY_CAR_WARNING,
835 Notification.CATEGORY_CAR_INFORMATION);
836 int id = 0;
837 for (String category: categories) {
838 final StatusBarNotification sbn =
839 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
840 sbn.getNotification().category = category;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400841 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700842 sbn.getId(), sbn.getNotification(), sbn.getUserId());
843 }
844 waitForIdle();
845 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
846 }
847
848
849 /**
850 * Confirm restricted notification categories only apply to automotive.
851 */
852 @Test
853 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
854 mService.isSystemUid = false;
855 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
856 .thenReturn(false);
857 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
858 Notification.CATEGORY_CAR_WARNING,
859 Notification.CATEGORY_CAR_INFORMATION);
860 int id = 0;
861 for (String category: categories) {
862 final StatusBarNotification sbn =
863 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
864 sbn.getNotification().category = category;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400865 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700866 sbn.getId(), sbn.getNotification(), sbn.getUserId());
867 }
868 waitForIdle();
869 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
870 }
871
872 /**
873 * Confirm if a non-system user tries to use the car categories on a automotive device that
874 * they will get a security exception
875 */
876 @Test
877 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
878 mService.isSystemUid = false;
879 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
880 .thenReturn(true);
881 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
882 Notification.CATEGORY_CAR_WARNING,
883 Notification.CATEGORY_CAR_INFORMATION);
884 for (String category: categories) {
885 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
886 sbn.getNotification().category = category;
887 try {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400888 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700889 sbn.getId(), sbn.getNotification(), sbn.getUserId());
890 fail("Calls from non system apps should not allow use of restricted categories");
891 } catch (SecurityException e) {
892 // pass
893 }
894 }
895 waitForIdle();
896 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
897 }
898
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400899 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400900 public void testBlockedNotifications_blockedByAssistant() throws Exception {
901 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500902 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400903
904 NotificationChannel channel = new NotificationChannel("id", "name",
905 NotificationManager.IMPORTANCE_HIGH);
906 NotificationRecord r = generateNotificationRecord(channel);
907 mService.addEnqueuedNotification(r);
908
Julia Reynolds27c0a962018-12-10 12:37:28 -0500909 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400910 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500911 Adjustment adjustment = new Adjustment(
912 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
913 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400914
915 NotificationManagerService.PostNotificationRunnable runnable =
916 mService.new PostNotificationRunnable(r.getKey());
917 runnable.run();
918 waitForIdle();
919
920 verify(mUsageStats, never()).registerPostedByApp(any());
921 }
922
923 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500924 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400925 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400926 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500927 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -0400928 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500929 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400930 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500931 }
932
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500933 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500934 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400935 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400936 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400937 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500938 waitForIdle();
939 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500940 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500941 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400942 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500943 }
944
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500945 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500946 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400947 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400948 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500949 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400950 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400951 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400952 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500953 waitForIdle();
954 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500955 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500956 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400957 assertEquals(0, mService.getNotificationRecordCount());
958 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
959 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
960 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500961 }
962
963 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500964 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -0400965 NotificationRecord r = generateNotificationRecord(null);
966 final StatusBarNotification sbn = r.sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400967 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400968 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500969 mBinderService.cancelNotificationsFromListener(null, null);
970 waitForIdle();
971 StatusBarNotification[] notifs =
972 mBinderService.getActiveNotifications(sbn.getPackageName());
973 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400974 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500975 }
976
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500977 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500978 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
979 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400980 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400981 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500982 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500983 waitForIdle();
984 StatusBarNotification[] notifs =
985 mBinderService.getActiveNotifications(sbn.getPackageName());
986 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400987 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -0400988 }
989
990 @Test
991 public void testUserInitiatedClearAll_noLeak() throws Exception {
992 final NotificationRecord n = generateNotificationRecord(
993 mTestNotificationChannel, 1, "group", true);
994
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400995 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -0400996 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
997 waitForIdle();
998
Julia Reynolds503ed942017-10-04 16:04:56 -0400999 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001000 n.getUserId());
1001 waitForIdle();
1002 StatusBarNotification[] notifs =
1003 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1004 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001005 assertEquals(0, mService.getNotificationRecordCount());
1006 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1007 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1008 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001009 }
1010
1011 @Test
1012 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1013 final NotificationRecord parent = generateNotificationRecord(
1014 mTestNotificationChannel, 1, "group1", true);
1015 final NotificationRecord child = generateNotificationRecord(
1016 mTestNotificationChannel, 2, "group1", false);
1017
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001018 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001019 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001020 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001021 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1022 waitForIdle();
1023
1024 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1025 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001026 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001027 }
1028
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001029 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001030 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1031 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1032 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001033 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001034 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1035 }
1036 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1037 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001038
Julia Reynolds503ed942017-10-04 16:04:56 -04001039 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001040 }
1041
1042 @Test
1043 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1044 final NotificationRecord parent = generateNotificationRecord(
1045 mTestNotificationChannel, 1, "group1", true);
1046 final NotificationRecord parentAsChild = generateNotificationRecord(
1047 mTestNotificationChannel, 1, "group1", false);
1048 final NotificationRecord child = generateNotificationRecord(
1049 mTestNotificationChannel, 2, "group1", false);
1050
1051 // fully post parent notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001052 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001053 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1054 waitForIdle();
1055
1056 // enqueue the child several times
1057 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001058 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001059 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1060 }
1061 // make the parent a child, which will cancel the child notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001062 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001063 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1064 parentAsChild.sbn.getUserId());
1065 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001066
Julia Reynolds503ed942017-10-04 16:04:56 -04001067 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001068 }
1069
1070 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001071 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1072 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001073 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001074 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001075 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001076 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001077 waitForIdle();
1078 StatusBarNotification[] notifs =
1079 mBinderService.getActiveNotifications(sbn.getPackageName());
1080 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001081 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001082 }
1083
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001084 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001085 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1086 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001087 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
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(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001090 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1091 waitForIdle();
1092 StatusBarNotification[] notifs =
1093 mBinderService.getActiveNotifications(sbn.getPackageName());
1094 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001095 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001096 }
1097
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001098 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001099 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1100 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001101 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001102 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001103 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1104 waitForIdle();
1105 StatusBarNotification[] notifs =
1106 mBinderService.getActiveNotifications(sbn.getPackageName());
1107 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001108 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001109 }
1110
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001111 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001112 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1113 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001114 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001115 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001116 // Null pkg is how we signal a user switch.
1117 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1118 waitForIdle();
1119 StatusBarNotification[] notifs =
1120 mBinderService.getActiveNotifications(sbn.getPackageName());
1121 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001122 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001123 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001124
1125 @Test
Beverly40239d92017-07-07 10:20:41 -04001126 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1127 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1128 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001129 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Beverly40239d92017-07-07 10:20:41 -04001130 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1131 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1132 waitForIdle();
1133 StatusBarNotification[] notifs =
1134 mBinderService.getActiveNotifications(sbn.getPackageName());
1135 assertEquals(0, notifs.length);
1136 }
1137
1138 @Test
1139 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1140 final NotificationRecord notif = generateNotificationRecord(
1141 mTestNotificationChannel, 1, "group", true);
1142 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001143 mService.addNotification(notif);
1144 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001145 notif.getUserId(), 0, null);
1146 waitForIdle();
1147 StatusBarNotification[] notifs =
1148 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1149 assertEquals(0, notifs.length);
1150 }
1151
1152 @Test
1153 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1154 final NotificationRecord notif = generateNotificationRecord(
1155 mTestNotificationChannel, 1, "group", true);
1156 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001157 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001158
Julia Reynolds503ed942017-10-04 16:04:56 -04001159 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001160 notif.getUserId());
1161 waitForIdle();
1162 StatusBarNotification[] notifs =
1163 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1164 assertEquals(1, notifs.length);
1165 }
1166
1167 @Test
1168 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1169 final NotificationRecord parent = generateNotificationRecord(
1170 mTestNotificationChannel, 1, "group", true);
1171 final NotificationRecord child = generateNotificationRecord(
1172 mTestNotificationChannel, 2, "group", false);
1173 final NotificationRecord child2 = generateNotificationRecord(
1174 mTestNotificationChannel, 3, "group", false);
1175 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1176 final NotificationRecord newGroup = generateNotificationRecord(
1177 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001178 mService.addNotification(parent);
1179 mService.addNotification(child);
1180 mService.addNotification(child2);
1181 mService.addNotification(newGroup);
1182 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001183 waitForIdle();
1184 StatusBarNotification[] notifs =
1185 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1186 assertEquals(1, notifs.length);
1187 }
1188
1189 @Test
1190 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1191 final NotificationRecord parent = generateNotificationRecord(
1192 mTestNotificationChannel, 1, "group", true);
1193 final NotificationRecord child = generateNotificationRecord(
1194 mTestNotificationChannel, 2, "group", false);
1195 final NotificationRecord child2 = generateNotificationRecord(
1196 mTestNotificationChannel, 3, "group", false);
1197 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1198 final NotificationRecord newGroup = generateNotificationRecord(
1199 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001200 mService.addNotification(parent);
1201 mService.addNotification(child);
1202 mService.addNotification(child2);
1203 mService.addNotification(newGroup);
1204 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001205 parent.getUserId());
1206 waitForIdle();
1207 StatusBarNotification[] notifs =
1208 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1209 assertEquals(1, notifs.length);
1210 }
1211
1212 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001213 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
1214 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001215 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001216 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001217 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001218 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1219 sbn.getUserId());
1220 waitForIdle();
1221 StatusBarNotification[] notifs =
1222 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001223 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001224 }
1225
1226 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001227 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1228 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1229 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001230 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001231 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001232 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1233 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001234 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001235 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -04001236 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001237 waitForIdle();
1238 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001239 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001240 }
1241
1242 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001243 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1244 throws Exception {
1245 final NotificationRecord parent = generateNotificationRecord(
1246 mTestNotificationChannel, 1, "group", true);
1247 final NotificationRecord child = generateNotificationRecord(
1248 mTestNotificationChannel, 2, "group", false);
1249 final NotificationRecord child2 = generateNotificationRecord(
1250 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001251 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001252 final NotificationRecord newGroup = generateNotificationRecord(
1253 mTestNotificationChannel, 4, "group2", false);
1254 mService.addNotification(parent);
1255 mService.addNotification(child);
1256 mService.addNotification(child2);
1257 mService.addNotification(newGroup);
1258 mService.getBinderService().cancelNotificationsFromListener(null, null);
1259 waitForIdle();
1260 StatusBarNotification[] notifs =
1261 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1262 assertEquals(0, notifs.length);
1263 }
1264
1265 @Test
1266 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1267 throws Exception {
1268 final NotificationRecord parent = generateNotificationRecord(
1269 mTestNotificationChannel, 1, "group", true);
1270 final NotificationRecord child = generateNotificationRecord(
1271 mTestNotificationChannel, 2, "group", false);
1272 final NotificationRecord child2 = generateNotificationRecord(
1273 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001274 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001275 final NotificationRecord newGroup = generateNotificationRecord(
1276 mTestNotificationChannel, 4, "group2", false);
1277 mService.addNotification(parent);
1278 mService.addNotification(child);
1279 mService.addNotification(child2);
1280 mService.addNotification(newGroup);
1281 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1282 child2.sbn.getKey(), newGroup.sbn.getKey()};
1283 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1284 waitForIdle();
1285 StatusBarNotification[] notifs =
1286 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1287 assertEquals(1, notifs.length);
1288 }
1289
1290 @Test
1291 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1292 final NotificationRecord parent = generateNotificationRecord(
1293 mTestNotificationChannel, 1, "group", true);
1294 final NotificationRecord child = generateNotificationRecord(
1295 mTestNotificationChannel, 2, "group", false);
1296 final NotificationRecord child2 = generateNotificationRecord(
1297 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001298 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001299 final NotificationRecord newGroup = generateNotificationRecord(
1300 mTestNotificationChannel, 4, "group2", false);
1301 mService.addNotification(parent);
1302 mService.addNotification(child);
1303 mService.addNotification(child2);
1304 mService.addNotification(newGroup);
1305 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1306 parent.getUserId());
1307 waitForIdle();
1308 StatusBarNotification[] notifs =
1309 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1310 assertEquals(0, notifs.length);
1311 }
1312
1313 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001314 public void testFindGroupNotificationsLocked() throws Exception {
1315 // make sure the same notification can be found in both lists and returned
1316 final NotificationRecord group1 = generateNotificationRecord(
1317 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001318 mService.addEnqueuedNotification(group1);
1319 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001320
1321 // should not be returned
1322 final NotificationRecord group2 = generateNotificationRecord(
1323 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001324 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001325 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1326 waitForIdle();
1327
1328 // should not be returned
1329 final NotificationRecord nonGroup = generateNotificationRecord(
1330 mTestNotificationChannel, 3, null, false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001331 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001332 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1333 waitForIdle();
1334
1335 // same group, child, should be returned
1336 final NotificationRecord group1Child = generateNotificationRecord(
1337 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001338 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001339 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1340 waitForIdle();
1341
1342 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001343 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001344 group1.sbn.getUserId());
1345 assertEquals(3, inGroup1.size());
1346 for (NotificationRecord record : inGroup1) {
1347 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1348 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1349 }
1350 }
1351
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001352 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001353 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1354 final NotificationRecord notif = generateNotificationRecord(
1355 mTestNotificationChannel, 1, "group", true);
1356 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1357 mService.addNotification(notif);
1358 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1359 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1360 waitForIdle();
1361 StatusBarNotification[] notifs =
1362 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1363 assertEquals(0, notifs.length);
1364 }
1365
1366 @Test
1367 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1368 throws Exception {
1369 final NotificationRecord parent = generateNotificationRecord(
1370 mTestNotificationChannel, 1, "group", true);
1371 final NotificationRecord child = generateNotificationRecord(
1372 mTestNotificationChannel, 2, "group", false);
1373 final NotificationRecord child2 = generateNotificationRecord(
1374 mTestNotificationChannel, 3, "group", false);
1375 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1376 final NotificationRecord newGroup = generateNotificationRecord(
1377 mTestNotificationChannel, 4, "group2", false);
1378 mService.addNotification(parent);
1379 mService.addNotification(child);
1380 mService.addNotification(child2);
1381 mService.addNotification(newGroup);
1382 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1383 child2.sbn.getKey(), newGroup.sbn.getKey()};
1384 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1385 waitForIdle();
1386 StatusBarNotification[] notifs =
1387 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1388 assertEquals(0, notifs.length);
1389 }
1390
1391 @Test
1392 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1393 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1394 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001395 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001396 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1397 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1398 waitForIdle();
1399 StatusBarNotification[] notifs =
1400 mBinderService.getActiveNotifications(sbn.getPackageName());
1401 assertEquals(0, notifs.length);
1402 }
1403
1404 @Test
1405 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1406 final NotificationRecord notif = generateNotificationRecord(
1407 mTestNotificationChannel, 1, "group", true);
1408 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1409 mService.addNotification(notif);
1410 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1411 notif.getUserId(), 0, null);
1412 waitForIdle();
1413 StatusBarNotification[] notifs =
1414 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1415 assertEquals(0, notifs.length);
1416 }
1417
1418 @Test
1419 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1420 final NotificationRecord notif = generateNotificationRecord(
1421 mTestNotificationChannel, 1, "group", true);
1422 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1423 mService.addNotification(notif);
1424
1425 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1426 notif.getUserId());
1427 waitForIdle();
1428 StatusBarNotification[] notifs =
1429 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1430 assertEquals(1, notifs.length);
1431 }
1432
1433 @Test
1434 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1435 final NotificationRecord parent = generateNotificationRecord(
1436 mTestNotificationChannel, 1, "group", true);
1437 final NotificationRecord child = generateNotificationRecord(
1438 mTestNotificationChannel, 2, "group", false);
1439 final NotificationRecord child2 = generateNotificationRecord(
1440 mTestNotificationChannel, 3, "group", false);
1441 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1442 final NotificationRecord newGroup = generateNotificationRecord(
1443 mTestNotificationChannel, 4, "group2", false);
1444 mService.addNotification(parent);
1445 mService.addNotification(child);
1446 mService.addNotification(child2);
1447 mService.addNotification(newGroup);
1448 mService.getBinderService().cancelNotificationsFromListener(null, null);
1449 waitForIdle();
1450 StatusBarNotification[] notifs =
1451 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1452 assertEquals(1, notifs.length);
1453 }
1454
1455 @Test
1456 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1457 throws Exception {
1458 final NotificationRecord parent = generateNotificationRecord(
1459 mTestNotificationChannel, 1, "group", true);
1460 final NotificationRecord child = generateNotificationRecord(
1461 mTestNotificationChannel, 2, "group", false);
1462 final NotificationRecord child2 = generateNotificationRecord(
1463 mTestNotificationChannel, 3, "group", false);
1464 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1465 final NotificationRecord newGroup = generateNotificationRecord(
1466 mTestNotificationChannel, 4, "group2", false);
1467 mService.addNotification(parent);
1468 mService.addNotification(child);
1469 mService.addNotification(child2);
1470 mService.addNotification(newGroup);
1471 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1472 child2.sbn.getKey(), newGroup.sbn.getKey()};
1473 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1474 waitForIdle();
1475 StatusBarNotification[] notifs =
1476 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1477 assertEquals(0, notifs.length);
1478 }
1479
1480 @Test
1481 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1482 final NotificationRecord parent = generateNotificationRecord(
1483 mTestNotificationChannel, 1, "group", true);
1484 final NotificationRecord child = generateNotificationRecord(
1485 mTestNotificationChannel, 2, "group", false);
1486 final NotificationRecord child2 = generateNotificationRecord(
1487 mTestNotificationChannel, 3, "group", false);
1488 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1489 final NotificationRecord newGroup = generateNotificationRecord(
1490 mTestNotificationChannel, 4, "group2", false);
1491 mService.addNotification(parent);
1492 mService.addNotification(child);
1493 mService.addNotification(child2);
1494 mService.addNotification(newGroup);
1495 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1496 parent.getUserId());
1497 waitForIdle();
1498 StatusBarNotification[] notifs =
1499 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1500 assertEquals(1, notifs.length);
1501 }
1502
1503 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001504 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001505 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001506 mService.setPreferencesHelper(mPreferencesHelper);
1507 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001508 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001509 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001510
Julia Reynoldsbad42972017-04-25 13:52:49 -04001511 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001512 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001513 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001514 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001515 anyString(), anyInt(), eq("foo"), anyBoolean());
1516 }
1517
1518 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001519 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001520 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001521 mService.setPreferencesHelper(mPreferencesHelper);
1522 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001523 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001524 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001525
Julia Reynoldsbad42972017-04-25 13:52:49 -04001526 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001527 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001528 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001529 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001530 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001531 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001532
1533 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001534 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001535 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001536
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001537 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001538 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1539 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1540
1541 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1542 captor.getValue().getAction());
1543 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001544 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1545 }
1546
1547 @Test
1548 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1549 mService.setPreferencesHelper(mPreferencesHelper);
1550
1551 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1552 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001553 }
1554
1555 @Test
1556 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001557 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001558
1559 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1560 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1561 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1562
1563 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1564 captor.getValue().getAction());
1565 assertEquals(PKG, captor.getValue().getPackage());
1566 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1567 }
1568
1569 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001570 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
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(mTestNotificationChannel);
1575
1576 NotificationChannel updatedChannel =
1577 new NotificationChannel(mTestNotificationChannel.getId(),
1578 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1579
1580 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1581 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1582 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1583
1584 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1585 captor.getValue().getAction());
1586 assertEquals(PKG, captor.getValue().getPackage());
1587 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001588 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001589 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1590 }
1591
1592 @Test
1593 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1594 NotificationChannel existingChannel =
1595 new NotificationChannel(mTestNotificationChannel.getId(),
1596 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001597 mService.setPreferencesHelper(mPreferencesHelper);
1598 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001599 eq(mTestNotificationChannel.getId()), anyBoolean()))
1600 .thenReturn(existingChannel);
1601
1602 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1603 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1604 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1605
1606 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1607 captor.getValue().getAction());
1608 assertEquals(PKG, captor.getValue().getPackage());
1609 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001610 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001611 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1612 }
1613
1614 @Test
1615 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1616 NotificationChannel existingChannel =
1617 new NotificationChannel(mTestNotificationChannel.getId(),
1618 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001619 mService.setPreferencesHelper(mPreferencesHelper);
1620 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001621 eq(mTestNotificationChannel.getId()), anyBoolean()))
1622 .thenReturn(existingChannel);
1623
1624 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1625 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1626 }
1627
1628 @Test
1629 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1630 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001631 mService.setPreferencesHelper(mPreferencesHelper);
1632 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001633 .thenReturn(existing);
1634
1635 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1636 updated.setBlocked(true);
1637
1638 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1639 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1640 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1641
1642 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1643 captor.getValue().getAction());
1644 assertEquals(PKG, captor.getValue().getPackage());
1645 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001646 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001647 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1648 }
1649
1650 @Test
1651 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1652 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1653 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001654 mService.setPreferencesHelper(mPreferencesHelper);
1655 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001656 .thenReturn(existing);
1657
1658 mBinderService.updateNotificationChannelGroupForPackage(
1659 PKG, 0, new NotificationChannelGroup("id", "name"));
1660 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1661 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1662
1663 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1664 captor.getValue().getAction());
1665 assertEquals(PKG, captor.getValue().getPackage());
1666 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001667 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001668 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1669 }
1670
1671 @Test
1672 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1673 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001674 mService.setPreferencesHelper(mPreferencesHelper);
1675 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001676 .thenReturn(existing);
1677
1678 mBinderService.updateNotificationChannelGroupForPackage(
1679 PKG, 0, new NotificationChannelGroup("id", "new name"));
1680 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1681 }
1682
1683 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001684 public void testCreateChannelNotifyListener() throws Exception {
1685 List<String> associations = new ArrayList<>();
1686 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001687 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001688 mService.setPreferencesHelper(mPreferencesHelper);
1689 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001690 eq(mTestNotificationChannel.getId()), anyBoolean()))
1691 .thenReturn(mTestNotificationChannel);
1692 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001693 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001694 eq(channel2.getId()), anyBoolean()))
1695 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001696 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1697 eq(channel2), anyBoolean(), anyBoolean()))
1698 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001699
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001700 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001701 mBinderService.createNotificationChannels(PKG,
1702 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001703 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001704 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001705 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001706 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001707 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001708 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1709 }
1710
1711 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001712 public void testCreateChannelGroupNotifyListener() throws Exception {
1713 List<String> associations = new ArrayList<>();
1714 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001715 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001716 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001717 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1718 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1719
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001720 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001721 mBinderService.createNotificationChannelGroups(PKG,
1722 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001723 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001724 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001725 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001726 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001727 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001728 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1729 }
1730
1731 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001732 public void testUpdateChannelNotifyListener() throws Exception {
1733 List<String> associations = new ArrayList<>();
1734 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001735 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001736 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001737 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001738 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001739 eq(mTestNotificationChannel.getId()), anyBoolean()))
1740 .thenReturn(mTestNotificationChannel);
1741
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001742 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001743 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001744 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001745 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001746 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1747 }
1748
1749 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001750 public void testDeleteChannelNotifyListener() throws Exception {
1751 List<String> associations = new ArrayList<>();
1752 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001753 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001754 mService.setPreferencesHelper(mPreferencesHelper);
1755 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001756 eq(mTestNotificationChannel.getId()), anyBoolean()))
1757 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001758 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001759 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001760 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001761 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001762 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1763 }
1764
1765 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001766 public void testDeleteChannelGroupNotifyListener() throws Exception {
1767 List<String> associations = new ArrayList<>();
1768 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001769 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001770 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001771 mService.setPreferencesHelper(mPreferencesHelper);
1772 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001773 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001774 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001775 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001776 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001777 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001778 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1779 }
1780
1781 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001782 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001783 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001784 List<String> associations = new ArrayList<>();
1785 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001786 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001787 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001788 eq(mTestNotificationChannel.getId()), anyBoolean()))
1789 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001790
1791 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001792 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001793
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001794 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001795 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001796
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001797 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001798 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001799 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1800 }
1801
1802 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001803 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001804 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001805 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001806 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001807
1808 try {
1809 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001810 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001811 fail("listeners that don't have a companion device shouldn't be able to call this");
1812 } catch (SecurityException e) {
1813 // pass
1814 }
1815
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001816 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001817 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001818
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001819 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001820 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1821 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1822 }
1823
1824 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001825 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001826 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001827 List<String> associations = new ArrayList<>();
1828 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001829 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001830 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04001831 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001832 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001833 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001834
1835 try {
1836 mBinderService.updateNotificationChannelFromPrivilegedListener(
1837 null, PKG, UserHandle.ALL, mTestNotificationChannel);
1838 fail("incorrectly allowed a change to a user listener cannot see");
1839 } catch (SecurityException e) {
1840 // pass
1841 }
1842
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001843 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001844 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001845
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001846 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001847 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001848 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1849 }
1850
1851 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001852 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001853 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001854 List<String> associations = new ArrayList<>();
1855 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001856 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001857
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001858 mBinderService.getNotificationChannelsFromPrivilegedListener(
1859 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001860
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001861 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001862 anyString(), anyInt(), anyBoolean());
1863 }
1864
1865 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001866 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001867 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001868 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001869 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001870
1871 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001872 mBinderService.getNotificationChannelsFromPrivilegedListener(
1873 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001874 fail("listeners that don't have a companion device shouldn't be able to call this");
1875 } catch (SecurityException e) {
1876 // pass
1877 }
1878
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001879 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001880 anyString(), anyInt(), anyBoolean());
1881 }
1882
1883 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001884 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
1885 throws Exception {
1886 mService.setPreferencesHelper(mPreferencesHelper);
1887 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1888 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
1889
1890 mBinderService.getNotificationChannelsFromPrivilegedListener(
1891 null, PKG, Process.myUserHandle());
1892
1893 verify(mPreferencesHelper, times(1)).getNotificationChannels(
1894 anyString(), anyInt(), anyBoolean());
1895 }
1896
1897 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04001898 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
1899 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001900 mService.setPreferencesHelper(mPreferencesHelper);
1901 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1902 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
1903
1904 try {
1905 mBinderService.getNotificationChannelsFromPrivilegedListener(
1906 null, PKG, Process.myUserHandle());
1907 fail("listeners that don't have a companion device shouldn't be able to call this");
1908 } catch (SecurityException e) {
1909 // pass
1910 }
1911
1912 verify(mPreferencesHelper, never()).getNotificationChannels(
1913 anyString(), anyInt(), anyBoolean());
1914 }
1915
1916 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001917 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001918 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001919 List<String> associations = new ArrayList<>();
1920 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001921 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001922 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1923 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001924 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001925
1926 try {
1927 mBinderService.getNotificationChannelsFromPrivilegedListener(
1928 null, PKG, Process.myUserHandle());
1929 fail("listener getting channels from a user they cannot see");
1930 } catch (SecurityException e) {
1931 // pass
1932 }
1933
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001934 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001935 anyString(), anyInt(), anyBoolean());
1936 }
1937
1938 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001939 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001940 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001941 List<String> associations = new ArrayList<>();
1942 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001943 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001944
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001945 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1946 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001947
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001948 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001949 }
1950
1951 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001952 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001953 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001954 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001955 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001956
1957 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001958 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1959 null, PKG, Process.myUserHandle());
1960 fail("listeners that don't have a companion device shouldn't be able to call this");
1961 } catch (SecurityException e) {
1962 // pass
1963 }
1964
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001965 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001966 }
1967
1968 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001969 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001970 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001971 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001972 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001973 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1974 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001975 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001976 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001977 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1978 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001979 fail("listeners that don't have a companion device shouldn't be able to call this");
1980 } catch (SecurityException e) {
1981 // pass
1982 }
1983
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001984 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001985 }
Julia Reynoldsda781472017-04-12 09:41:16 -04001986
1987 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04001988 public void testHasCompanionDevice_failure() throws Exception {
1989 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
1990 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04001991 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04001992 }
Julia Reynolds727a7282017-04-13 10:54:01 -04001993
1994 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04001995 public void testHasCompanionDevice_noService() {
1996 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04001997
Julia Reynolds503ed942017-10-04 16:04:56 -04001998 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04001999 }
2000
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002001 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002002 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2003 final NotificationRecord notification = generateNotificationRecord(
2004 mTestNotificationChannel, 1, null, true);
2005 mService.addNotification(notification);
2006 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2007
2008 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2009 mService.new SnoozeNotificationRunnable(
2010 notification.getKey(), 100, null);
2011 snoozeNotificationRunnable.run();
2012 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2013 mService.new SnoozeNotificationRunnable(
2014 notification.getKey(), 100, null);
2015 snoozeNotificationRunnable.run();
2016
2017 // snooze twice
2018 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2019 }
2020
2021 @Test
2022 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2023 final NotificationRecord notification = generateNotificationRecord(
2024 mTestNotificationChannel, 1, "group", true);
2025 mService.addNotification(notification);
2026 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2027
2028 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2029 mService.new SnoozeNotificationRunnable(
2030 notification.getKey(), 100, null);
2031 snoozeNotificationRunnable.run();
2032 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2033 mService.new SnoozeNotificationRunnable(
2034 notification.getKey(), 100, null);
2035 snoozeNotificationRunnable.run();
2036
2037 // snooze twice
2038 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2039 }
2040
2041 @Test
2042 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2043 final NotificationRecord notification = generateNotificationRecord(
2044 mTestNotificationChannel, 1, "group", true);
2045 final NotificationRecord notification2 = generateNotificationRecord(
2046 mTestNotificationChannel, 2, "group", true);
2047 mService.addNotification(notification);
2048 mService.addNotification(notification2);
2049 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2050 when(mSnoozeHelper.getNotifications(
2051 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2052
2053 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2054 mService.new SnoozeNotificationRunnable(
2055 notification.getKey(), 100, null);
2056 snoozeNotificationRunnable.run();
2057 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2058 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2059 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2060 mService.new SnoozeNotificationRunnable(
2061 notification.getKey(), 100, null);
2062 snoozeNotificationRunnable.run();
2063
2064 // snooze twice
2065 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2066 }
2067
2068 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002069 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2070 final NotificationRecord nonGrouped = generateNotificationRecord(
2071 mTestNotificationChannel, 1, null, false);
2072 final NotificationRecord grouped = generateNotificationRecord(
2073 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002074 mService.addNotification(grouped);
2075 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002076
2077 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002078 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002079 nonGrouped.getKey(), 100, null);
2080 snoozeNotificationRunnable.run();
2081
2082 // only snooze the one notification
2083 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002084 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002085 }
2086
2087 @Test
2088 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2089 final NotificationRecord parent = generateNotificationRecord(
2090 mTestNotificationChannel, 1, "group", true);
2091 final NotificationRecord child = generateNotificationRecord(
2092 mTestNotificationChannel, 2, "group", false);
2093 final NotificationRecord child2 = generateNotificationRecord(
2094 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002095 mService.addNotification(parent);
2096 mService.addNotification(child);
2097 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002098
2099 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002100 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002101 parent.getKey(), 100, null);
2102 snoozeNotificationRunnable.run();
2103
2104 // snooze parent and children
2105 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2106 }
2107
2108 @Test
2109 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2110 final NotificationRecord parent = generateNotificationRecord(
2111 mTestNotificationChannel, 1, "group", true);
2112 final NotificationRecord child = generateNotificationRecord(
2113 mTestNotificationChannel, 2, "group", false);
2114 final NotificationRecord child2 = generateNotificationRecord(
2115 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002116 mService.addNotification(parent);
2117 mService.addNotification(child);
2118 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002119
2120 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002121 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002122 child2.getKey(), 100, null);
2123 snoozeNotificationRunnable.run();
2124
2125 // only snooze the one child
2126 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2127 }
2128
2129 @Test
2130 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2131 final NotificationRecord parent = generateNotificationRecord(
2132 mTestNotificationChannel, 1, "group", true);
2133 assertTrue(parent.sbn.getNotification().isGroupSummary());
2134 final NotificationRecord child = generateNotificationRecord(
2135 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002136 mService.addNotification(parent);
2137 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002138
2139 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002140 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002141 child.getKey(), 100, null);
2142 snoozeNotificationRunnable.run();
2143
2144 // snooze child and summary
2145 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2146 }
2147
2148 @Test
2149 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2150 final NotificationRecord child = generateNotificationRecord(
2151 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002152 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002153
2154 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002155 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002156 child.getKey(), 100, null);
2157 snoozeNotificationRunnable.run();
2158
2159 // snooze child only
2160 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2161 }
2162
2163 @Test
2164 public void testPostGroupChild_unsnoozeParent() throws Exception {
2165 final NotificationRecord child = generateNotificationRecord(
2166 mTestNotificationChannel, 2, "group", false);
2167
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002168 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002169 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2170 waitForIdle();
2171
2172 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2173 anyString(), anyInt(), eq(child.getGroupKey()));
2174 }
2175
2176 @Test
2177 public void testPostNonGroup_noUnsnoozing() throws Exception {
2178 final NotificationRecord record = generateNotificationRecord(
2179 mTestNotificationChannel, 2, null, false);
2180
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002181 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002182 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2183 waitForIdle();
2184
2185 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2186 }
2187
2188 @Test
2189 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2190 final NotificationRecord parent = generateNotificationRecord(
2191 mTestNotificationChannel, 2, "group", true);
2192
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002193 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002194 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2195 waitForIdle();
2196
2197 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2198 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002199
2200 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002201 public void testSetListenerAccessForUser() throws Exception {
2202 UserHandle user = UserHandle.of(10);
2203 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002204 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2205
Julia Reynolds92febc32017-10-26 11:30:31 -04002206
2207 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2208 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2209 c.flattenToString(), user.getIdentifier(), true, true);
2210 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2211 c.flattenToString(), user.getIdentifier(), false, true);
2212 verify(mAssistants, never()).setPackageOrComponentEnabled(
2213 any(), anyInt(), anyBoolean(), anyBoolean());
2214 }
2215
2216 @Test
2217 public void testSetAssistantAccessForUser() throws Exception {
2218 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002219 List<UserInfo> uis = new ArrayList<>();
2220 UserInfo ui = new UserInfo();
2221 ui.id = 10;
2222 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002223 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002224 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2225
2226 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002227
2228 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2229 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2230 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002231 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002232 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2233 c.flattenToString(), user.getIdentifier(), false, true);
2234 verify(mListeners, never()).setPackageOrComponentEnabled(
2235 any(), anyInt(), anyBoolean(), anyBoolean());
2236 }
2237
2238 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002239 public void testGetAssistantAllowedForUser() throws Exception {
2240 UserHandle user = UserHandle.of(10);
2241 try {
2242 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2243 } catch (IllegalStateException e) {
2244 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2245 throw e;
2246 }
2247 }
2248 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2249 }
2250
2251 @Test
2252 public void testGetAssistantAllowed() throws Exception {
2253 try {
2254 mBinderService.getAllowedNotificationAssistant();
2255 } catch (IllegalStateException e) {
2256 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2257 throw e;
2258 }
2259 }
2260 verify(mAssistants, times(1)).getAllowedComponents(0);
2261 }
2262
2263 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002264 public void testSetDndAccessForUser() throws Exception {
2265 UserHandle user = UserHandle.of(10);
2266 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002267 mBinderService.setNotificationPolicyAccessGrantedForUser(
2268 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002269
2270 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2271 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2272 c.getPackageName(), user.getIdentifier(), true, true);
2273 verify(mAssistants, never()).setPackageOrComponentEnabled(
2274 any(), anyInt(), anyBoolean(), anyBoolean());
2275 verify(mListeners, never()).setPackageOrComponentEnabled(
2276 any(), anyInt(), anyBoolean(), anyBoolean());
2277 }
2278
2279 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002280 public void testSetListenerAccess() throws Exception {
2281 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002282 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002283
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002284 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002285 c.flattenToString(), 0, true, true);
2286 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2287 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002288 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002289 any(), anyInt(), anyBoolean(), anyBoolean());
2290 }
2291
2292 @Test
2293 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002294 List<UserInfo> uis = new ArrayList<>();
2295 UserInfo ui = new UserInfo();
2296 ui.id = 0;
2297 uis.add(ui);
2298 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002299 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002300
2301 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002302
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002303 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002304 c.flattenToString(), 0, true, true);
2305 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2306 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002307 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002308 any(), anyInt(), anyBoolean(), anyBoolean());
2309 }
2310
2311 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002312 public void testSetAssistantAccess_multiProfile() throws Exception {
2313 List<UserInfo> uis = new ArrayList<>();
2314 UserInfo ui = new UserInfo();
2315 ui.id = 0;
2316 uis.add(ui);
2317 UserInfo ui10 = new UserInfo();
2318 ui10.id = 10;
2319 uis.add(ui10);
2320 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2321 ComponentName c = ComponentName.unflattenFromString("package/Component");
2322
2323 mBinderService.setNotificationAssistantAccessGranted(c, true);
2324
2325 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2326 c.flattenToString(), 0, true, true);
2327 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2328 c.flattenToString(), 10, true, true);
2329 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2330 c.flattenToString(), 0, false, true);
2331 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2332 c.flattenToString(), 10, false, true);
2333 verify(mListeners, never()).setPackageOrComponentEnabled(
2334 any(), anyInt(), anyBoolean(), anyBoolean());
2335 }
2336
2337 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002338 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2339 ArrayList<ComponentName> componentList = new ArrayList<>();
2340 ComponentName c = ComponentName.unflattenFromString("package/Component");
2341 componentList.add(c);
2342 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002343 List<UserInfo> uis = new ArrayList<>();
2344 UserInfo ui = new UserInfo();
2345 ui.id = 0;
2346 uis.add(ui);
2347 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002348
Julia Reynolds4afe2642019-05-01 08:42:24 -04002349 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002350
2351 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2352 c.flattenToString(), 0, true, false);
2353 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2354 c.flattenToString(), 0, false, false);
2355 verify(mListeners, never()).setPackageOrComponentEnabled(
2356 any(), anyInt(), anyBoolean(), anyBoolean());
2357 }
2358
2359 @Test
2360 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002361 List<UserInfo> uis = new ArrayList<>();
2362 UserInfo ui = new UserInfo();
2363 ui.id = 10;
2364 uis.add(ui);
2365 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002366 ArrayList<ComponentName> componentList = new ArrayList<>();
2367 ComponentName c = ComponentName.unflattenFromString("package/Component");
2368 componentList.add(c);
2369 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002370 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002371
Julia Reynolds4afe2642019-05-01 08:42:24 -04002372 mBinderService.setNotificationAssistantAccessGrantedForUser(
2373 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002374
2375 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2376 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002377 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002378 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2379 c.flattenToString(), user.getIdentifier(), false, false);
2380 verify(mListeners, never()).setPackageOrComponentEnabled(
2381 any(), anyInt(), anyBoolean(), anyBoolean());
2382 }
2383
2384 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002385 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2386 throws Exception {
2387 List<UserInfo> uis = new ArrayList<>();
2388 UserInfo ui = new UserInfo();
2389 ui.id = 0;
2390 uis.add(ui);
2391 UserInfo ui10 = new UserInfo();
2392 ui10.id = 10;
2393 uis.add(ui10);
2394 UserHandle user = ui.getUserHandle();
2395 ArrayList<ComponentName> componentList = new ArrayList<>();
2396 ComponentName c = ComponentName.unflattenFromString("package/Component");
2397 componentList.add(c);
2398 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2399 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2400
2401 mBinderService.setNotificationAssistantAccessGrantedForUser(
2402 null, user.getIdentifier(), true);
2403
2404 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2405 c.flattenToString(), user.getIdentifier(), true, false);
2406 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2407 c.flattenToString(), ui10.id, true, false);
2408 verify(mAssistants).setUserSet(0, true);
2409 verify(mAssistants).setUserSet(10, true);
2410 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2411 c.flattenToString(), user.getIdentifier(), false, false);
2412 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2413 c.flattenToString(), ui10.id, false, false);
2414 verify(mListeners, never()).setPackageOrComponentEnabled(
2415 any(), anyInt(), anyBoolean(), anyBoolean());
2416 }
2417
2418 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002419 public void testSetDndAccess() throws Exception {
2420 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002421
2422 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002423
2424 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2425 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002426 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002427 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002428 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002429 any(), anyInt(), anyBoolean(), anyBoolean());
2430 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002431
2432 @Test
2433 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2434 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2435 ComponentName c = ComponentName.unflattenFromString("package/Component");
2436 mBinderService.setNotificationListenerAccessGranted(c, true);
2437
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002438 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002439 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002440 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002441 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002442 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002443 any(), anyInt(), anyBoolean(), anyBoolean());
2444 }
2445
2446 @Test
2447 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2448 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2449 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002450 List<UserInfo> uis = new ArrayList<>();
2451 UserInfo ui = new UserInfo();
2452 ui.id = 0;
2453 uis.add(ui);
2454 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2455
Julia Reynolds68263d12017-06-21 14:21:19 -04002456 mBinderService.setNotificationAssistantAccessGranted(c, true);
2457
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002458 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002459 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002460 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002461 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002462 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002463 any(), anyInt(), anyBoolean(), anyBoolean());
2464 }
2465
2466 @Test
2467 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2468 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2469 ComponentName c = ComponentName.unflattenFromString("package/Component");
2470 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2471
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002472 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002473 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002474 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002475 anyString(), anyInt(), anyBoolean(), anyBoolean());
2476 verify(mAssistants, never()).setPackageOrComponentEnabled(
2477 any(), anyInt(), anyBoolean(), anyBoolean());
2478 }
2479
2480 @Test
2481 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2482 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2483 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2484 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002485
2486 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002487
2488 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2489 c.flattenToString(), 0, true, true);
2490 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002491 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002492 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002493 any(), anyInt(), anyBoolean(), anyBoolean());
2494 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002495
2496 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002497 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2498 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2499 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2500 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002501 List<UserInfo> uis = new ArrayList<>();
2502 UserInfo ui = new UserInfo();
2503 ui.id = 0;
2504 uis.add(ui);
2505 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2506
2507 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002508
2509 verify(mListeners, never()).setPackageOrComponentEnabled(
2510 anyString(), anyInt(), anyBoolean(), anyBoolean());
2511 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2512 c.flattenToString(), 0, false, true);
2513 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2514 c.flattenToString(), 0, true, true);
2515 }
2516
2517 @Test
2518 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2519 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2520 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2521 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002522
2523 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002524
2525 verify(mListeners, never()).setPackageOrComponentEnabled(
2526 anyString(), anyInt(), anyBoolean(), anyBoolean());
2527 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2528 c.getPackageName(), 0, true, true);
2529 verify(mAssistants, never()).setPackageOrComponentEnabled(
2530 any(), anyInt(), anyBoolean(), anyBoolean());
2531 }
2532
2533 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002534 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2535 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002536 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002537 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002538 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002539 runnable.run();
2540 waitForIdle();
2541
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002542 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002543 }
2544
2545 @Test
2546 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2547 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002548 NotificationRecord r =
2549 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002550 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002551
2552 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002553 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002554 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002555 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002556 runnable.run();
2557 waitForIdle();
2558
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002559 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002560 }
2561
2562 @Test
2563 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2564 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002565 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2566 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002567 mService.addNotification(r);
2568 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002569
2570 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002571 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002572 runnable.run();
2573 waitForIdle();
2574
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002575 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002576 }
Beverly40239d92017-07-07 10:20:41 -04002577
Julia Reynolds4db59552017-06-30 13:34:01 -04002578 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002579 public void testDontAutogroupIfCritical() throws Exception {
2580 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2581 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2582 mService.addEnqueuedNotification(r);
2583 NotificationManagerService.PostNotificationRunnable runnable =
2584 mService.new PostNotificationRunnable(r.getKey());
2585 runnable.run();
2586
2587 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2588 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2589 runnable = mService.new PostNotificationRunnable(r.getKey());
2590 mService.addEnqueuedNotification(r);
2591
2592 runnable.run();
2593 waitForIdle();
2594
2595 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2596 }
2597
2598 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002599 public void testNoFakeColorizedPermission() throws Exception {
2600 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2601 Notification.Builder nb = new Notification.Builder(mContext,
2602 mTestNotificationChannel.getId())
2603 .setContentTitle("foo")
2604 .setColorized(true)
2605 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2606 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002607 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
2608 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002609 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2610
2611 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2612 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2613 waitForIdle();
2614
Julia Reynolds503ed942017-10-04 16:04:56 -04002615 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds4db59552017-06-30 13:34:01 -04002616 PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
2617
2618 assertFalse(posted.getNotification().isColorized());
2619 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002620
2621 @Test
2622 public void testGetNotificationCountLocked() throws Exception {
2623 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002624 NotificationRecord r =
2625 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002626 mService.addEnqueuedNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002627 }
2628 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002629 NotificationRecord r =
2630 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002631 mService.addNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002632 }
2633
2634 // another package
2635 Notification n =
2636 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2637 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2638 .build();
2639
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002640 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2641 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002642 NotificationRecord otherPackage =
2643 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002644 mService.addEnqueuedNotification(otherPackage);
2645 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002646
2647 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002648 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002649 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002650 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002651 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002652 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002653 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002654 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002655
2656 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002657 assertEquals(39,
Julia Reynolds503ed942017-10-04 16:04:56 -04002658 mService.getNotificationCountLocked(PKG, userId, 0, "tag"));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002659 }
2660
2661 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002662 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002663 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002664 mService.setRankingHandler(rh);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002665
2666 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002667 mService.addNotification(r);
2668 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002669
2670 verify(rh, times(1)).requestSort();
2671 }
2672
2673 @Test
2674 public void testRemoveAutogroup_requestsSort() throws Exception {
2675 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002676 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002677
2678 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2679 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002680 mService.addNotification(r);
2681 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002682
Julia Reynolds51710712017-07-19 13:48:07 -04002683 verify(rh, times(1)).requestSort();
2684 }
2685
2686 @Test
2687 public void testReaddAutogroup_noSort() throws Exception {
2688 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002689 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002690
2691 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2692 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002693 mService.addNotification(r);
2694 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002695
2696 verify(rh, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002697 }
2698
2699 @Test
2700 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002701 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002702 NotificationManagerService.WorkerHandler handler = mock(
2703 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002704 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002705
2706 Map<String, Answer> answers = getSignalExtractorSideEffects();
2707 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002708 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002709 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002710 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002711
2712 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2713
Julia Reynolds503ed942017-10-04 16:04:56 -04002714 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002715 }
2716 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2717 }
2718
2719 @Test
2720 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002721 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002722 NotificationManagerService.WorkerHandler handler = mock(
2723 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002724 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002725
2726 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002727 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002728
Julia Reynolds503ed942017-10-04 16:04:56 -04002729 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002730 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002731 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002732
2733 @Test
2734 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002735 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002736 + "<ranking></ranking>"
2737 + "<enabled_listeners>"
2738 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2739 + "</enabled_listeners>"
2740 + "<enabled_assistants>"
2741 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2742 + "</enabled_assistants>"
2743 + "<dnd_apps>"
2744 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2745 + "</dnd_apps>"
2746 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002747 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002748 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2749 false,
2750 UserHandle.USER_ALL);
2751 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2752 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2753 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002754
2755 // numbers are inflated for setup
2756 verify(mListeners, times(1)).migrateToXml();
2757 verify(mConditionProviders, times(1)).migrateToXml();
2758 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002759 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002760 }
2761
2762 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04002763 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
2764 final String upgradeXml = "<notification-policy version=\"1\">"
2765 + "<snoozed-notifications>></snoozed-notifications>"
2766 + "</notification-policy>";
2767 mService.readPolicyXml(
2768 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2769 false,
2770 UserHandle.USER_ALL);
2771 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class));
2772 }
2773
2774 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002775 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2776 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002777 + "<ranking></ranking>"
2778 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002779 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002780 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2781 false,
2782 UserHandle.USER_ALL);
2783 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2784 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2785 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002786
2787 // numbers are inflated for setup
2788 verify(mListeners, times(2)).migrateToXml();
2789 verify(mConditionProviders, times(2)).migrateToXml();
2790 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002791 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002792 }
2793
Annie Meng8b646fd2019-02-01 18:46:42 +00002794 @Test
2795 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2796 final String policyXml = "<notification-policy version=\"1\">"
2797 + "<ranking></ranking>"
2798 + "<enabled_listeners>"
2799 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2800 + "</enabled_listeners>"
2801 + "<enabled_assistants>"
2802 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2803 + "</enabled_assistants>"
2804 + "<dnd_apps>"
2805 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2806 + "</dnd_apps>"
2807 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002808 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00002809 mService.readPolicyXml(
2810 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2811 true,
2812 10);
2813 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2814 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2815 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2816 }
2817
2818 @Test
2819 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2820 final String policyXml = "<notification-policy version=\"1\">"
2821 + "<ranking></ranking>"
2822 + "<enabled_listeners>"
2823 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2824 + "</enabled_listeners>"
2825 + "<enabled_assistants>"
2826 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2827 + "</enabled_assistants>"
2828 + "<dnd_apps>"
2829 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2830 + "</dnd_apps>"
2831 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002832 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00002833 mService.readPolicyXml(
2834 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2835 true,
2836 10);
2837 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
2838 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
2839 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
2840 }
Beverlyd4f96492017-08-02 13:36:11 -04002841
2842 @Test
2843 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
2844 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002845 mService.mZenModeHelper = mZenModeHelper;
2846 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04002847 new Intent(Intent.ACTION_LOCALE_CHANGED));
2848
2849 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
2850 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002851
2852 @Test
2853 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06002854 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002855 final ApplicationInfo legacy = new ApplicationInfo();
2856 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
2857 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
2858 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002859 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
2860 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002861 getContext().setMockPackageManager(mPackageManagerClient);
2862
2863 Notification.Builder nb = new Notification.Builder(mContext,
2864 NotificationChannel.DEFAULT_CHANNEL_ID)
2865 .setContentTitle("foo")
2866 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002867 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002868 .setPriority(Notification.PRIORITY_MIN);
2869
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002870 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
2871 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002872
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002873 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
2874 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002875 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002876
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002877 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002878 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002879
2880 nb = new Notification.Builder(mContext)
2881 .setContentTitle("foo")
2882 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002883 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002884 .setPriority(Notification.PRIORITY_MIN);
2885
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002886 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
2887 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002888
2889 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
2890 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2891 waitForIdle();
2892 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002893 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002894
2895 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04002896 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002897 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
2898 }
Julia Reynolds503ed942017-10-04 16:04:56 -04002899
2900 @Test
2901 public void testStats_updatedOnDirectReply() throws Exception {
2902 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2903 mService.addNotification(r);
2904
2905 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
2906 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00002907 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04002908 }
2909
2910 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002911 public void testStats_updatedOnUserExpansion() throws Exception {
2912 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002913 mService.addNotification(r);
2914
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002915 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
2916 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002917 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002918 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002919
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002920 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
2921 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002922 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002923 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2924 }
2925
2926 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002927 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
2928 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2929 mService.addNotification(r);
2930
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002931 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
2932 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002933 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002934 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
2935
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002936 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
2937 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002938 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002939 verify(mAssistants).notifyAssistantExpansionChangedLocked(
2940 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002941 }
2942
2943 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04002944 public void testStats_updatedOnViewSettings() throws Exception {
2945 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2946 mService.addNotification(r);
2947
2948 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
2949 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
2950 }
2951
2952 @Test
2953 public void testStats_updatedOnVisibilityChanged() throws Exception {
2954 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2955 mService.addNotification(r);
2956
Dieter Hsud39f0d52018-04-14 02:08:30 +08002957 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002958 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2959 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
2960 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2961 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2962 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
2963 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2964 }
2965
2966 @Test
2967 public void testStats_dismissalSurface() throws Exception {
2968 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2969 mService.addNotification(r);
2970
Dieter Hsud39f0d52018-04-14 02:08:30 +08002971 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002972 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002973 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2974 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04002975 waitForIdle();
2976
2977 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
2978 }
2979
2980 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002981 public void testStats_dismissalSentiment() throws Exception {
2982 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2983 mService.addNotification(r);
2984
2985 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2986 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2987 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2988 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
2989 waitForIdle();
2990
2991 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
2992 r.getStats().getDismissalSentiment());
2993 }
2994
2995 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002996 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002997 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2998 mService.addNotification(r);
2999 NotificationManagerService.WorkerHandler handler = mock(
3000 NotificationManagerService.WorkerHandler.class);
3001 mService.setHandler(handler);
3002
Julia Reynolds70aaea72018-07-13 13:38:34 -04003003 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3004
Julia Reynolds503ed942017-10-04 16:04:56 -04003005 Bundle signals = new Bundle();
3006 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003007 USER_SENTIMENT_NEGATIVE);
3008 Adjustment adjustment = new Adjustment(
3009 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3010 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3011
3012 waitForIdle();
3013
3014 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3015 }
3016
3017 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003018 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003019 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3020 mService.addNotification(r);
3021 NotificationManagerService.WorkerHandler handler = mock(
3022 NotificationManagerService.WorkerHandler.class);
3023 mService.setHandler(handler);
3024
3025 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003026 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003027 Adjustment adjustment = new Adjustment(
3028 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3029 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3030 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3031
3032 waitForIdle();
3033
3034 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3035 verify(handler, times(1)).scheduleCancelNotification(any());
3036 }
3037
3038 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003039 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3040 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3041 mService.addEnqueuedNotification(r);
3042 NotificationManagerService.WorkerHandler handler = mock(
3043 NotificationManagerService.WorkerHandler.class);
3044 mService.setHandler(handler);
3045 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3046
3047 Bundle signals = new Bundle();
3048 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3049 USER_SENTIMENT_NEGATIVE);
3050 Adjustment adjustment = new Adjustment(
3051 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3052 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3053
3054 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3055 }
3056
3057 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003058 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003059 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3060 mService.addEnqueuedNotification(r);
3061 NotificationManagerService.WorkerHandler handler = mock(
3062 NotificationManagerService.WorkerHandler.class);
3063 mService.setHandler(handler);
3064 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3065
3066 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003067 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003068 Adjustment adjustment = new Adjustment(
3069 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3070 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3071
3072 assertEquals(IMPORTANCE_LOW, r.getImportance());
3073 }
3074
3075 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003076 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3077 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3078 mService.addEnqueuedNotification(r);
3079 NotificationManagerService.WorkerHandler handler = mock(
3080 NotificationManagerService.WorkerHandler.class);
3081 mService.setHandler(handler);
3082 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3083
3084 Bundle signals = new Bundle();
3085 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3086 USER_SENTIMENT_NEGATIVE);
3087 Adjustment adjustment = new Adjustment(
3088 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3089 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3090
3091 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3092
3093 waitForIdle();
3094
3095 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3096 }
3097
3098 @Test
3099 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3100 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3101 mService.addNotification(r);
3102 NotificationManagerService.WorkerHandler handler = mock(
3103 NotificationManagerService.WorkerHandler.class);
3104 mService.setHandler(handler);
3105 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3106
3107 Bundle signals = new Bundle();
3108 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3109 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003110 Adjustment adjustment = new Adjustment(
3111 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3112 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3113
3114 waitForIdle();
3115
3116 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3117 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003118
3119 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003120 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3121 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3122 mService.addNotification(r);
3123 NotificationManagerService.WorkerHandler handler = mock(
3124 NotificationManagerService.WorkerHandler.class);
3125 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003126 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003127
3128 Bundle signals = new Bundle();
3129 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003130 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003131 Adjustment adjustment = new Adjustment(
3132 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3133 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3134
3135 waitForIdle();
3136
3137 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3138 }
3139
3140 @Test
3141 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3142 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3143 mService.addEnqueuedNotification(r);
3144 NotificationManagerService.WorkerHandler handler = mock(
3145 NotificationManagerService.WorkerHandler.class);
3146 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003147 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003148
3149 Bundle signals = new Bundle();
3150 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003151 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003152 Adjustment adjustment = new Adjustment(
3153 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3154 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3155
Julia Reynolds70aaea72018-07-13 13:38:34 -04003156 assertEquals(USER_SENTIMENT_NEGATIVE,
Julia Reynolds666ccf02018-06-18 10:19:20 -04003157 r.getUserSentiment());
3158 }
3159
3160 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003161 public void testRestore() throws Exception {
3162 int systemChecks = mService.countSystemChecks;
3163 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
3164 assertEquals(1, mService.countSystemChecks - systemChecks);
3165 }
3166
3167 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003168 public void testBackupEmptySound() throws Exception {
3169 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3170 channel.setSound(Uri.EMPTY, null);
3171
3172 XmlSerializer serializer = new FastXmlSerializer();
3173 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3174 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3175 channel.writeXmlForBackup(serializer, getContext());
3176
3177 XmlPullParser parser = Xml.newPullParser();
3178 parser.setInput(new BufferedInputStream(
3179 new ByteArrayInputStream(baos.toByteArray())), null);
3180 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3181 restored.populateFromXmlForRestore(parser, getContext());
3182
3183 assertNull(restored.getSound());
3184 }
3185
3186 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003187 public void testBackup() throws Exception {
3188 int systemChecks = mService.countSystemChecks;
3189 mBinderService.getBackupPayload(1);
3190 assertEquals(1, mService.countSystemChecks - systemChecks);
3191 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003192
3193 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003194 public void testEmptyVibration_noException() throws Exception {
3195 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3196 channel.setVibrationPattern(new long[0]);
3197
3198 XmlSerializer serializer = new FastXmlSerializer();
3199 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3200 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3201 channel.writeXml(serializer);
3202 }
3203
3204 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003205 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003206 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003207 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003208 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3209 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003210 message1.setData("",
3211 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003212 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003213 message2.setData("",
3214 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003215
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003216 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003217 .setContentTitle("foo")
3218 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3219 .setStyle(new Notification.MessagingStyle("")
3220 .addMessage(message1)
3221 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003222 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3223 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003224
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003225 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003226 reset(mUgm);
3227 reset(mUgmInternal);
3228 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003229 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
3230 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003231 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003232 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003233 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003234 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3235
3236 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003237 .setContentTitle("foo")
3238 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3239 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003240 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3241 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003242
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003243 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003244 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003245 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
3246 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003247 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3248 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003249
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003250 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003251 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003252 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
3253 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003254 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003255 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003256
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003257 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003258 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003259 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
3260 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003261 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003262 anyInt(), anyInt());
3263 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003264
3265 @Test
Robin Leed107af62018-04-27 13:55:56 +02003266 public void testVisitUris() throws Exception {
3267 final Uri audioContents = Uri.parse("content://com.example/audio");
3268 final Uri backgroundImage = Uri.parse("content://com.example/background");
3269
3270 Bundle extras = new Bundle();
3271 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3272 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3273
3274 Notification n = new Notification.Builder(mContext, "a")
3275 .setContentTitle("notification with uris")
3276 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3277 .addExtras(extras)
3278 .build();
3279
3280 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3281 n.visitUris(visitor);
3282 verify(visitor, times(1)).accept(eq(audioContents));
3283 verify(visitor, times(1)).accept(eq(backgroundImage));
3284 }
3285
3286 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003287 public void testSetNotificationPolicy_preP_setOldFields() {
3288 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3289 mService.mZenModeHelper = mZenModeHelper;
3290 NotificationManager.Policy userPolicy =
3291 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3292 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3293
3294 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3295 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3296
3297 int expected = SUPPRESSED_EFFECT_BADGE
3298 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003299 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3300 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003301 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3302
3303 assertEquals(expected, actual);
3304 }
3305
3306 @Test
3307 public void testSetNotificationPolicy_preP_setNewFields() {
3308 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3309 mService.mZenModeHelper = mZenModeHelper;
3310 NotificationManager.Policy userPolicy =
3311 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3312 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3313
3314 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3315 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3316
3317 int expected = SUPPRESSED_EFFECT_BADGE;
3318 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3319
3320 assertEquals(expected, actual);
3321 }
3322
3323 @Test
3324 public void testSetNotificationPolicy_preP_setOldNewFields() {
3325 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3326 mService.mZenModeHelper = mZenModeHelper;
3327 NotificationManager.Policy userPolicy =
3328 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3329 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3330
3331 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3332 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3333
3334 int expected =
3335 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3336 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3337
3338 assertEquals(expected, actual);
3339 }
3340
3341 @Test
3342 public void testSetNotificationPolicy_P_setOldFields() {
3343 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3344 mService.mZenModeHelper = mZenModeHelper;
3345 NotificationManager.Policy userPolicy =
3346 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3347 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3348
3349 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3350 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3351
3352 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3353 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3354 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3355 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3356
3357 assertEquals(expected, actual);
3358 }
3359
3360 @Test
3361 public void testSetNotificationPolicy_P_setNewFields() {
3362 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3363 mService.mZenModeHelper = mZenModeHelper;
3364 NotificationManager.Policy userPolicy =
3365 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3366 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3367
3368 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3369 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3370 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3371
3372 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3373 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3374 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3375 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3376
3377 assertEquals(expected, actual);
3378 }
3379
3380 @Test
3381 public void testSetNotificationPolicy_P_setOldNewFields() {
3382 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3383 mService.mZenModeHelper = mZenModeHelper;
3384 NotificationManager.Policy userPolicy =
3385 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3386 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3387
3388 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3389 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3390
3391 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3392 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3393
3394 assertEquals(expected, actual);
3395
3396 appPolicy = new NotificationManager.Policy(0, 0, 0,
3397 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3398 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3399
3400 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3401 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3402 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3403
3404 assertEquals(expected, actual);
3405 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003406
3407 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003408 public void testVisualDifference_foreground() {
3409 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3410 .setContentTitle("foo");
3411 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3412 nb1.build(), new UserHandle(mUid), null, 0);
3413 NotificationRecord r1 =
3414 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3415
3416 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3417 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3418 .setContentTitle("bar");
3419 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3420 nb2.build(), new UserHandle(mUid), null, 0);
3421 NotificationRecord r2 =
3422 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3423
3424 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3425 }
3426
3427 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003428 public void testVisualDifference_diffTitle() {
3429 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3430 .setContentTitle("foo");
3431 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3432 nb1.build(), new UserHandle(mUid), null, 0);
3433 NotificationRecord r1 =
3434 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3435
3436 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3437 .setContentTitle("bar");
3438 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3439 nb2.build(), new UserHandle(mUid), null, 0);
3440 NotificationRecord r2 =
3441 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3442
3443 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3444 }
3445
3446 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003447 public void testVisualDifference_inboxStyle() {
3448 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3449 .setStyle(new Notification.InboxStyle()
3450 .addLine("line1").addLine("line2"));
3451 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3452 nb1.build(), new UserHandle(mUid), null, 0);
3453 NotificationRecord r1 =
3454 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3455
3456 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3457 .setStyle(new Notification.InboxStyle()
3458 .addLine("line1").addLine("line2_changed"));
3459 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3460 nb2.build(), new UserHandle(mUid), null, 0);
3461 NotificationRecord r2 =
3462 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3463
3464 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3465
3466 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3467 .setStyle(new Notification.InboxStyle()
3468 .addLine("line1"));
3469 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3470 nb3.build(), new UserHandle(mUid), null, 0);
3471 NotificationRecord r3 =
3472 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3473
3474 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3475
3476 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3477 .setStyle(new Notification.InboxStyle()
3478 .addLine("line1").addLine("line2").addLine("line3"));
3479 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3480 nb4.build(), new UserHandle(mUid), null, 0);
3481 NotificationRecord r4 =
3482 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3483
3484 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3485
3486 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3487 .setContentText("not an inbox");
3488 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3489 nb5.build(), new UserHandle(mUid), null, 0);
3490 NotificationRecord r5 =
3491 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3492
3493 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3494 }
3495
3496 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003497 public void testVisualDifference_diffText() {
3498 Notification.Builder nb1 = new Notification.Builder(mContext, "")
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 .setContentText("bar");
3507 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3508 nb2.build(), new UserHandle(mUid), null, 0);
3509 NotificationRecord r2 =
3510 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3511
3512 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3513 }
3514
3515 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003516 public void testVisualDifference_sameText() {
3517 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3518 .setContentText("foo");
3519 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3520 nb1.build(), new UserHandle(mUid), null, 0);
3521 NotificationRecord r1 =
3522 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3523
3524 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3525 .setContentText("foo");
3526 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3527 nb2.build(), new UserHandle(mUid), null, 0);
3528 NotificationRecord r2 =
3529 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3530
3531 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3532 }
3533
3534 @Test
3535 public void testVisualDifference_sameTextButStyled() {
3536 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3537 .setContentText(Html.fromHtml("<b>foo</b>"));
3538 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3539 nb1.build(), new UserHandle(mUid), null, 0);
3540 NotificationRecord r1 =
3541 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3542
3543 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3544 .setContentText(Html.fromHtml("<b>foo</b>"));
3545 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3546 nb2.build(), new UserHandle(mUid), null, 0);
3547 NotificationRecord r2 =
3548 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3549
3550 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3551 }
3552
3553 @Test
3554 public void testVisualDifference_diffTextButStyled() {
3555 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3556 .setContentText(Html.fromHtml("<b>foo</b>"));
3557 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3558 nb1.build(), new UserHandle(mUid), null, 0);
3559 NotificationRecord r1 =
3560 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3561
3562 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3563 .setContentText(Html.fromHtml("<b>bar</b>"));
3564 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3565 nb2.build(), new UserHandle(mUid), null, 0);
3566 NotificationRecord r2 =
3567 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3568
3569 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3570 }
3571
3572 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003573 public void testVisualDifference_diffProgress() {
3574 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3575 .setProgress(100, 90, false);
3576 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3577 nb1.build(), new UserHandle(mUid), null, 0);
3578 NotificationRecord r1 =
3579 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3580
3581 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3582 .setProgress(100, 100, false);
3583 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3584 nb2.build(), new UserHandle(mUid), null, 0);
3585 NotificationRecord r2 =
3586 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3587
3588 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3589 }
3590
3591 @Test
3592 public void testVisualDifference_diffProgressNotDone() {
3593 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3594 .setProgress(100, 90, false);
3595 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3596 nb1.build(), new UserHandle(mUid), null, 0);
3597 NotificationRecord r1 =
3598 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3599
3600 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3601 .setProgress(100, 91, false);
3602 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3603 nb2.build(), new UserHandle(mUid), null, 0);
3604 NotificationRecord r2 =
3605 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3606
3607 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3608 }
Beverly5a20a5e2018-03-06 15:02:44 -05003609
3610 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003611 public void testVisualDifference_sameProgressStillDone() {
3612 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3613 .setProgress(100, 100, false);
3614 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3615 nb1.build(), new UserHandle(mUid), null, 0);
3616 NotificationRecord r1 =
3617 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3618
3619 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3620 .setProgress(100, 100, false);
3621 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3622 nb2.build(), new UserHandle(mUid), null, 0);
3623 NotificationRecord r2 =
3624 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3625
3626 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3627 }
3628
3629 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003630 public void testVisualDifference_summary() {
3631 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3632 .setGroup("bananas")
3633 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3634 .setContentText("foo");
3635 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3636 nb1.build(), new UserHandle(mUid), null, 0);
3637 NotificationRecord r1 =
3638 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3639
3640 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3641 .setGroup("bananas")
3642 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3643 .setContentText("bar");
3644 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3645 nb2.build(), new UserHandle(mUid), null, 0);
3646 NotificationRecord r2 =
3647 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3648
3649 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3650 }
3651
3652 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003653 public void testVisualDifference_summaryNewNotification() {
3654 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3655 .setGroup("bananas")
3656 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3657 .setContentText("bar");
3658 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3659 nb2.build(), new UserHandle(mUid), null, 0);
3660 NotificationRecord r2 =
3661 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3662
3663 assertFalse(mService.isVisuallyInterruptive(null, r2));
3664 }
3665
3666 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003667 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3668 // post 2 notification from this package
3669 final NotificationRecord notif1 = generateNotificationRecord(
3670 mTestNotificationChannel, 1, null, true);
3671 final NotificationRecord notif2 = generateNotificationRecord(
3672 mTestNotificationChannel, 2, null, false);
3673 mService.addNotification(notif1);
3674 mService.addNotification(notif2);
3675
3676 // on broadcast, hide the 2 notifications
3677 mService.simulatePackageSuspendBroadcast(true, PKG);
3678 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3679 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3680 assertEquals(2, captorHide.getValue().size());
3681
3682 // on broadcast, unhide the 2 notifications
3683 mService.simulatePackageSuspendBroadcast(false, PKG);
3684 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3685 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3686 assertEquals(2, captorUnhide.getValue().size());
3687 }
3688
3689 @Test
3690 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3691 // post 2 notification from this package
3692 final NotificationRecord notif1 = generateNotificationRecord(
3693 mTestNotificationChannel, 1, null, true);
3694 final NotificationRecord notif2 = generateNotificationRecord(
3695 mTestNotificationChannel, 2, null, false);
3696 mService.addNotification(notif1);
3697 mService.addNotification(notif2);
3698
3699 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3700 mService.simulatePackageSuspendBroadcast(true, "test_package");
3701 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3702 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3703 assertEquals(0, captor.getValue().size());
3704 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003705
3706 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003707 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3708 // Post 2 notifications from 2 packages
3709 NotificationRecord pkgA = new NotificationRecord(mContext,
3710 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3711 mService.addNotification(pkgA);
3712 NotificationRecord pkgB = new NotificationRecord(mContext,
3713 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3714 mService.addNotification(pkgB);
3715
3716 // on broadcast, hide one of the packages
3717 mService.simulatePackageDistractionBroadcast(
3718 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3719 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3720 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3721 assertEquals(1, captorHide.getValue().size());
3722 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3723
3724 // on broadcast, unhide the package
3725 mService.simulatePackageDistractionBroadcast(
3726 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3727 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3728 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3729 assertEquals(1, captorUnhide.getValue().size());
3730 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3731 }
3732
3733 @Test
3734 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3735 // Post 2 notifications from 2 packages
3736 NotificationRecord pkgA = new NotificationRecord(mContext,
3737 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3738 mService.addNotification(pkgA);
3739 NotificationRecord pkgB = new NotificationRecord(mContext,
3740 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3741 mService.addNotification(pkgB);
3742
3743 // on broadcast, hide one of the packages
3744 mService.simulatePackageDistractionBroadcast(
3745 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3746 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3747 verify(mListeners, times(2)).notifyHiddenLocked(captorHide.capture());
3748 assertEquals(2, captorHide.getValue().size());
3749 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3750 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3751
3752 // on broadcast, unhide the package
3753 mService.simulatePackageDistractionBroadcast(
3754 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3755 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3756 verify(mListeners, times(2)).notifyUnhiddenLocked(captorUnhide.capture());
3757 assertEquals(2, captorUnhide.getValue().size());
3758 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3759 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3760 }
3761
3762 @Test
3763 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3764 // post notification from this package
3765 final NotificationRecord notif1 = generateNotificationRecord(
3766 mTestNotificationChannel, 1, null, true);
3767 mService.addNotification(notif1);
3768
3769 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3770 mService.simulatePackageDistractionBroadcast(
3771 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3772 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3773 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3774 assertEquals(0, captor.getValue().size());
3775 }
3776
3777 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003778 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3779 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3780 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3781 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3782 .thenReturn(new String[] {"a", "b", "c"});
3783 when(mContext.getResources()).thenReturn(mResources);
3784
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003785 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003786 }
3787
3788 @Test
3789 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3790 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3791 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3792 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3793 .thenReturn(new String[] {"a", "b", "c"});
3794 when(mContext.getResources()).thenReturn(mResources);
3795
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003796 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003797 }
3798
3799 @Test
3800 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3801 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3802 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3803 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3804 .thenReturn(new String[] {"a", "b", "c"});
3805 when(mContext.getResources()).thenReturn(mResources);
3806
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003807 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003808 }
3809
3810 @Test
3811 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3812 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3813 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3814 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3815 .thenReturn(new String[] {"a", "b", "c"});
3816 when(mContext.getResources()).thenReturn(mResources);
3817
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003818 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003819 }
3820
3821 @Test
3822 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3823 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3824 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3825 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3826 .thenReturn(new String[] {"a", "b", "c"});
3827 when(mContext.getResources()).thenReturn(mResources);
3828
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003829 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003830 }
3831
3832 @Test
3833 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
3834 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3835 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3836 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3837 .thenReturn(new String[] {"a", "b", "c"});
3838 when(mContext.getResources()).thenReturn(mResources);
3839
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003840 assertEquals(true, mService.canUseManagedServices("d", 0, null));
3841 }
3842
3843 @Test
3844 public void testCanUseManagedServices_hasPermission() throws Exception {
3845 when(mPackageManager.checkPermission("perm", "pkg", 0))
3846 .thenReturn(PackageManager.PERMISSION_GRANTED);
3847
3848 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
3849 }
3850
3851 @Test
3852 public void testCanUseManagedServices_noPermission() throws Exception {
3853 when(mPackageManager.checkPermission("perm", "pkg", 0))
3854 .thenReturn(PackageManager.PERMISSION_DENIED);
3855
3856 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
3857 }
3858
3859 @Test
3860 public void testCanUseManagedServices_permDoesNotMatter() {
3861 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003862 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003863
3864 @Test
3865 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
3866 final NotificationRecord r = generateNotificationRecord(
3867 mTestNotificationChannel, 1, null, true);
3868 r.setTextChanged(true);
3869 mService.addNotification(r);
3870
3871 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
3872 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
3873 new NotificationVisibility[]{});
3874
3875 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3876 }
3877
3878 @Test
3879 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
3880 throws RemoteException {
3881 final NotificationRecord r = generateNotificationRecord(
3882 mTestNotificationChannel, 1, null, true);
3883 r.setTextChanged(true);
3884 mService.addNotification(r);
3885
3886 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
3887
3888 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3889 }
3890
3891 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003892 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003893 throws RemoteException {
3894 final NotificationRecord r = generateNotificationRecord(
3895 mTestNotificationChannel, 1, null, true);
3896 r.setInterruptive(true);
3897 mService.addNotification(r);
3898
3899 mService.maybeRecordInterruptionLocked(r);
3900 mService.maybeRecordInterruptionLocked(r);
3901
3902 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
3903 anyString(), anyString(), anyInt());
3904 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003905
3906 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08003907 public void testBubble() throws Exception {
3908 mBinderService.setBubblesAllowed(PKG, mUid, false);
3909 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05003910 }
3911
3912 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08003913 public void testUserApprovedBubblesForPackage() throws Exception {
3914 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3915 mBinderService.setBubblesAllowed(PKG, mUid, true);
3916 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3917 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3918 }
3919
3920 @Test
3921 public void testUserRejectsBubblesForPackage() throws Exception {
3922 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3923 mBinderService.setBubblesAllowed(PKG, mUid, false);
3924 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3925 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3926 }
3927
3928 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003929 public void testIsCallerInstantApp_primaryUser() throws Exception {
3930 ApplicationInfo info = new ApplicationInfo();
3931 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3932 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04003933 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003934
Julia Reynolds268647a2018-10-25 16:54:27 -04003935 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003936
3937 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04003938 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003939 }
3940
3941 @Test
3942 public void testIsCallerInstantApp_secondaryUser() throws Exception {
3943 ApplicationInfo info = new ApplicationInfo();
3944 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3945 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3946 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04003947 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003948
Julia Reynolds268647a2018-10-25 16:54:27 -04003949 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003950 }
3951
3952 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04003953 public void testIsCallerInstantApp_userAllNotification() throws Exception {
3954 ApplicationInfo info = new ApplicationInfo();
3955 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3956 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
3957 .thenReturn(info);
3958 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3959
3960 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
3961
3962 info.privateFlags = 0;
3963 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
3964 }
3965
3966 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003967 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
3968 ApplicationInfo info = new ApplicationInfo();
3969 info.uid = Binder.getCallingUid();
3970 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3971 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3972
3973 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
3974
3975 assertEquals(info.uid, actualUid);
3976 }
3977
3978 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003979 public void testResolveNotificationUid_sameApp() throws Exception {
3980 ApplicationInfo info = new ApplicationInfo();
3981 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04003982 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003983
3984 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
3985
3986 assertEquals(info.uid, actualUid);
3987 }
3988
3989 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003990 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003991 ApplicationInfo info = new ApplicationInfo();
3992 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003993 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003994
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003995 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
3996
3997 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003998 }
3999
4000 @Test
4001 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4002 ApplicationInfo info = new ApplicationInfo();
4003 info.uid = 1356347;
4004 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4005
4006 try {
4007 mService.resolveNotificationUid("caller", "caller", 9, 0);
4008 fail("Incorrect uid didn't throw security exception");
4009 } catch (SecurityException e) {
4010 // yay
4011 }
4012 }
4013
4014 @Test
4015 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4016 int expectedUid = 123;
4017
4018 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4019 mService.setPreferencesHelper(mPreferencesHelper);
4020 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4021 .thenReturn(true);
4022
4023 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4024 }
4025
4026 @Test
4027 public void testResolveNotificationUid_androidAllowed() throws Exception {
4028 int expectedUid = 123;
4029
4030 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4031 // no delegate
4032
4033 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4034 }
4035
4036 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004037 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4038 final String notReal = "NOT REAL";
4039 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4040 PackageManager.NameNotFoundException.class);
4041 ApplicationInfo ai = new ApplicationInfo();
4042 ai.uid = -1;
4043 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4044
4045 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4046 try {
4047 mInternalService.enqueueNotification(notReal, "android", 0, 0, "tag",
4048 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4049 fail("can't post notifications for nonexistent packages, even if you exist");
4050 } catch (SecurityException e) {
4051 // yay
4052 }
4053 }
4054
4055 @Test
4056 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4057 final String notReal = "NOT REAL";
4058 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4059 PackageManager.NameNotFoundException.class);
4060 ApplicationInfo ai = new ApplicationInfo();
4061 ai.uid = -1;
4062 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4063
4064 // unlike the post case, ignore instead of throwing
4065 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4066
4067 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4068 sbn.getId(), sbn.getUserId());
4069 }
4070
4071 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004072 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4073 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4074 // no delegate
4075
4076 try {
4077 mService.resolveNotificationUid("caller", "target", 9, 0);
4078 fail("Incorrect uid didn't throw security exception");
4079 } catch (SecurityException e) {
4080 // yay
4081 }
4082 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004083
4084 @Test
4085 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4086 Notification n = new Notification.Builder(mContext, "").build();
4087 n.flags |= FLAG_FOREGROUND_SERVICE;
4088
4089 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4090 n, new UserHandle(mUid), null, 0);
4091 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4092
4093 mService.addEnqueuedNotification(r);
4094
4095 mInternalService.removeForegroundServiceFlagFromNotification(
4096 PKG, r.sbn.getId(), r.sbn.getUserId());
4097
4098 waitForIdle();
4099
4100 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4101 }
4102
4103 @Test
4104 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4105 Notification n = new Notification.Builder(mContext, "").build();
4106 n.flags |= FLAG_FOREGROUND_SERVICE;
4107
4108 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4109 n, new UserHandle(mUid), null, 0);
4110 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4111
4112 mService.addNotification(r);
4113
4114 mInternalService.removeForegroundServiceFlagFromNotification(
4115 PKG, r.sbn.getId(), r.sbn.getUserId());
4116
4117 waitForIdle();
4118
4119 ArgumentCaptor<NotificationRecord> captor =
4120 ArgumentCaptor.forClass(NotificationRecord.class);
4121 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4122
4123 assertEquals(0, captor.getValue().getNotification().flags);
4124 }
Beverly58b24532018-10-02 09:08:23 -04004125
4126 @Test
4127 public void testAllowForegroundToasts() throws Exception {
4128 final String testPackage = "testPackageName";
4129 assertEquals(0, mService.mToastQueue.size());
4130 mService.isSystemUid = false;
4131
4132 // package is not suspended
4133 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4134 .thenReturn(false);
4135
4136 // notifications from this package are blocked by the user
4137 mService.setPreferencesHelper(mPreferencesHelper);
4138 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4139
4140 // this app is in the foreground
4141 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4142
4143 // enqueue toast -> toast should still enqueue
4144 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4145 new TestableToastCallback(), 2000, 0);
4146 assertEquals(1, mService.mToastQueue.size());
4147 }
4148
4149 @Test
4150 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4151 final String testPackage = "testPackageName";
4152 assertEquals(0, mService.mToastQueue.size());
4153 mService.isSystemUid = false;
4154
4155 // package is suspended
4156 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4157 .thenReturn(true);
4158
4159 // notifications from this package are NOT blocked by the user
4160 mService.setPreferencesHelper(mPreferencesHelper);
4161 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4162
4163 // enqueue toast -> no toasts enqueued
4164 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4165 new TestableToastCallback(), 2000, 0);
4166 assertEquals(0, mService.mToastQueue.size());
4167 }
4168
4169 @Test
4170 public void testDisallowToastsFromBlockedApps() throws Exception {
4171 final String testPackage = "testPackageName";
4172 assertEquals(0, mService.mToastQueue.size());
4173 mService.isSystemUid = false;
4174
4175 // package is not suspended
4176 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4177 .thenReturn(false);
4178
4179 // notifications from this package are blocked by the user
4180 mService.setPreferencesHelper(mPreferencesHelper);
4181 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4182
4183 // this app is NOT in the foreground
4184 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4185
4186 // enqueue toast -> no toasts enqueued
4187 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4188 new TestableToastCallback(), 2000, 0);
4189 assertEquals(0, mService.mToastQueue.size());
4190 }
4191
4192 @Test
4193 public void testAlwaysAllowSystemToasts() throws Exception {
4194 final String testPackage = "testPackageName";
4195 assertEquals(0, mService.mToastQueue.size());
4196 mService.isSystemUid = true;
4197
4198 // package is suspended
4199 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4200 .thenReturn(true);
4201
4202 // notifications from this package ARE blocked by the user
4203 mService.setPreferencesHelper(mPreferencesHelper);
4204 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4205
4206 // this app is NOT in the foreground
4207 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4208
4209 // enqueue toast -> system toast can still be enqueued
4210 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4211 new TestableToastCallback(), 2000, 0);
4212 assertEquals(1, mService.mToastQueue.size());
4213 }
Tony Mak29996702018-11-26 16:23:34 +00004214
4215 @Test
4216 public void testOnNotificationSmartReplySent() {
4217 final int replyIndex = 2;
4218 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004219 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004220 final boolean generatedByAssistant = true;
4221
4222 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004223 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004224 mService.addNotification(r);
4225
4226 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004227 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4228 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004229 verify(mAssistants).notifyAssistantSuggestedReplySent(
4230 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4231 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004232
4233 @Test
4234 public void testOnNotificationActionClick() {
4235 final int actionIndex = 2;
4236 final Notification.Action action =
4237 new Notification.Action.Builder(null, "text", null).build();
4238 final boolean generatedByAssistant = false;
4239
4240 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4241 mService.addNotification(r);
4242
4243 NotificationVisibility notificationVisibility =
4244 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4245 mService.mNotificationDelegate.onNotificationActionClick(
4246 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4247 generatedByAssistant);
4248 verify(mAssistants).notifyAssistantActionClicked(
4249 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4250 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004251
4252 @Test
4253 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4254 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4255 mService.addNotification(r);
4256
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004257 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4258 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004259 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4260 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4261 };
4262 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4263 new NotificationVisibility[0]);
4264
4265 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4266 }
4267
4268 @Test
4269 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4270 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4271 mService.addNotification(r);
4272
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004273 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4274 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004275
4276 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4277 }
4278
4279 @Test
4280 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4281 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4282 mService.addNotification(r);
4283
Julia Reynolds95334132018-12-19 11:15:35 -05004284 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004285 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4286 };
4287 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4288 new NotificationVisibility[0]);
4289
4290 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4291 }
Julia Reynolds95334132018-12-19 11:15:35 -05004292
4293 public void testReportSeen_delegated() {
4294 Notification.Builder nb =
4295 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4296 .setContentTitle("foo")
4297 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4298
4299 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4300 nb.build(), new UserHandle(mUid), null, 0);
4301 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4302
4303 mService.reportSeen(r);
4304 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4305
4306 }
4307
4308 @Test
4309 public void testReportSeen_notDelegated() {
4310 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4311
4312 mService.reportSeen(r);
4313 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4314 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004315
4316 @Test
4317 public void testNotificationStats_notificationError() {
4318 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4319 mService.addNotification(r);
4320
4321 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4322 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4323 new UserHandle(mUid), null, 0);
4324 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4325 mService.addEnqueuedNotification(update);
4326 assertNull(update.sbn.getNotification().getSmallIcon());
4327
4328 NotificationManagerService.PostNotificationRunnable runnable =
4329 mService.new PostNotificationRunnable(update.getKey());
4330 runnable.run();
4331 waitForIdle();
4332
4333 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4334 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4335 assertNotNull(captor.getValue());
4336 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004337
4338 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004339 public void testCanNotifyAsUser_crossUser() throws Exception {
4340 // same user no problem
4341 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4342
4343 // cross user, no permission, problem
4344 try {
4345 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4346 fail("Should not be callable cross user without cross user permission");
4347 } catch (SecurityException e) {
4348 // good
4349 }
4350
4351 // cross user, with permission, no problem
4352 TestablePermissions perms = mContext.getTestablePermissions();
4353 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4354 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4355 }
4356
4357 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004358 public void testgetNotificationChannels_crossUser() throws Exception {
4359 // same user no problem
4360 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4361
4362 // cross user, no permission, problem
4363 try {
4364 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4365 fail("Should not be callable cross user without cross user permission");
4366 } catch (SecurityException e) {
4367 // good
4368 }
4369
4370 // cross user, with permission, no problem
4371 TestablePermissions perms = mContext.getTestablePermissions();
4372 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4373 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4374 }
4375
4376 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004377 public void setDefaultAssistantForUser_fromConfigXml() {
4378 clearDeviceConfig();
4379 ComponentName xmlConfig = new ComponentName("config", "xml");
4380 when(mResources
4381 .getString(
4382 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4383 .thenReturn(xmlConfig.flattenToString());
4384 when(mContext.getResources()).thenReturn(mResources);
4385 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4386 .thenReturn(Collections.singleton(xmlConfig));
4387 mService.setNotificationAssistantAccessGrantedCallback(
4388 mNotificationAssistantAccessGrantedCallback);
4389
4390 mService.setDefaultAssistantForUser(0);
4391
4392 verify(mNotificationAssistantAccessGrantedCallback)
4393 .onGranted(eq(xmlConfig), eq(0), eq(true));
4394 }
4395
4396 @Test
4397 public void setDefaultAssistantForUser_fromDeviceConfig() {
4398 ComponentName xmlConfig = new ComponentName("xml", "config");
4399 ComponentName deviceConfig = new ComponentName("device", "config");
4400 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4401 when(mResources
4402 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4403 .thenReturn(xmlConfig.flattenToString());
4404 when(mContext.getResources()).thenReturn(mResources);
4405 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4406 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
4407 mService.setNotificationAssistantAccessGrantedCallback(
4408 mNotificationAssistantAccessGrantedCallback);
4409
4410 mService.setDefaultAssistantForUser(0);
4411
4412 verify(mNotificationAssistantAccessGrantedCallback)
4413 .onGranted(eq(deviceConfig), eq(0), eq(true));
4414 }
4415
4416 @Test
4417 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4418 ComponentName xmlConfig = new ComponentName("xml", "config");
4419 ComponentName deviceConfig = new ComponentName("device", "config");
4420 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4421 when(mResources
4422 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4423 .thenReturn(xmlConfig.flattenToString());
4424 when(mContext.getResources()).thenReturn(mResources);
4425 // Only xmlConfig is valid, deviceConfig is not.
4426 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4427 .thenReturn(Collections.singleton(xmlConfig));
4428 mService.setNotificationAssistantAccessGrantedCallback(
4429 mNotificationAssistantAccessGrantedCallback);
4430
4431 mService.setDefaultAssistantForUser(0);
4432
4433 verify(mNotificationAssistantAccessGrantedCallback)
4434 .onGranted(eq(xmlConfig), eq(0), eq(true));
4435 }
4436
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004437 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004438 public void testFlagBubble() throws RemoteException {
4439 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004440 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004441
4442 // Notif with bubble metadata but not our other misc requirements
4443 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4444 null /* tvExtender */, true /* isBubble */);
4445
4446 // Say we're foreground
4447 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4448 IMPORTANCE_FOREGROUND);
4449
4450 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4451 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4452 waitForIdle();
4453
4454 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4455 assertEquals(1, notifs.length);
4456 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4457 assertTrue(mService.getNotificationRecord(
4458 nr.sbn.getKey()).getNotification().isBubbleNotification());
4459 }
4460
4461 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004462 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4463 // Bubbles are allowed!
4464 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4465
4466 // Notif with bubble metadata but not our other misc requirements
4467 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4468 null /* tvExtender */, true /* isBubble */);
4469
4470 // Say we're foreground
4471 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4472 IMPORTANCE_FOREGROUND);
4473
4474 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4475 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4476 waitForIdle();
4477
4478 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4479 assertEquals(1, notifs.length);
4480 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4481 assertFalse(mService.getNotificationRecord(
4482 nr.sbn.getKey()).getNotification().isBubbleNotification());
4483 }
4484
4485 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004486 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004487 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004488 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004489
Mady Mellorbe797962019-04-01 16:04:24 -07004490 // Notif with bubble metadata but not our other misc requirements
4491 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4492 null /* tvExtender */, true /* isBubble */);
4493
4494 // Say we're foreground
4495 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4496 IMPORTANCE_FOREGROUND);
4497
4498 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4499 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4500 waitForIdle();
4501
4502 // yes allowed, yes foreground, yes bubble
4503 assertTrue(mService.getNotificationRecord(
4504 nr.sbn.getKey()).getNotification().isBubbleNotification());
4505 }
4506
4507 @Test
4508 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4509 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004510 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004511
4512 // Notif with bubble metadata but not our other misc requirements
4513 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4514 null /* tvExtender */, true /* isBubble */);
4515
4516 // Make sure we're NOT foreground
4517 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4518 IMPORTANCE_VISIBLE);
4519
4520 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4521 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4522 waitForIdle();
4523
4524 // yes allowed but NOT foreground, no bubble
4525 assertFalse(mService.getNotificationRecord(
4526 nr.sbn.getKey()).getNotification().isBubbleNotification());
4527 }
4528
4529 @Test
4530 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4531 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004532 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004533
4534 // Notif with bubble metadata but not our other misc requirements
4535 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4536 null /* tvExtender */, true /* isBubble */);
4537
4538 // Send notif when we're foreground
4539 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4540 IMPORTANCE_FOREGROUND);
4541 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4542 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4543 waitForIdle();
4544
4545 // yes allowed, yes foreground, yes bubble
4546 assertTrue(mService.getNotificationRecord(
4547 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4548
4549 // Send a new update when we're not foreground
4550 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4551 null /* tvExtender */, true /* isBubble */);
4552
4553 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4554 IMPORTANCE_VISIBLE);
4555 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4556 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4557 waitForIdle();
4558
4559 // yes allowed, previously foreground / flagged, yes bubble
4560 assertTrue(mService.getNotificationRecord(
4561 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4562
4563 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4564 assertEquals(1, notifs2.length);
4565 assertEquals(1, mService.getNotificationRecordCount());
4566 }
4567
4568 @Test
4569 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4570 throws RemoteException {
4571 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004572 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004573
4574 // Notif with bubble metadata but not our other misc requirements
4575 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4576 null /* tvExtender */, true /* isBubble */);
4577
4578 // Send notif when we're foreground
4579 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4580 IMPORTANCE_FOREGROUND);
4581 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4582 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4583 waitForIdle();
4584
4585 // yes allowed, yes foreground, yes bubble
4586 assertTrue(mService.getNotificationRecord(
4587 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4588
4589 // Remove the bubble
Julia Reynoldse4a47dd2019-06-07 13:40:59 -04004590 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", nr1.sbn.getId(),
Mady Mellorbe797962019-04-01 16:04:24 -07004591 nr1.sbn.getUserId());
4592 waitForIdle();
4593
4594 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4595 assertEquals(0, notifs.length);
4596 assertEquals(0, mService.getNotificationRecordCount());
4597
4598 // Send a new update when we're not foreground
4599 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4600 null /* tvExtender */, true /* isBubble */);
4601
4602 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4603 IMPORTANCE_VISIBLE);
4604 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4605 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4606 waitForIdle();
4607
4608 // yes allowed, but was removed & no foreground, so no bubble
4609 assertFalse(mService.getNotificationRecord(
4610 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4611
4612 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4613 assertEquals(1, notifs2.length);
4614 assertEquals(1, mService.getNotificationRecordCount());
4615 }
4616
4617 @Test
4618 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4619 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004620 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004621
4622 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004623 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004624 // Give it a person
4625 Person person = new Person.Builder()
4626 .setName("bubblebot")
4627 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004628 // It needs remote input to be bubble-able
4629 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4630 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4631 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4632 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4633 inputIntent).addRemoteInput(remoteInput)
4634 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004635 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004636 Notification.Builder nb = new Notification.Builder(mContext,
4637 mTestNotificationChannel.getId())
4638 .setContentTitle("foo")
4639 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004640 .setStyle(new Notification.MessagingStyle(person)
4641 .setConversationTitle("Bubble Chat")
4642 .addMessage("Hello?",
4643 SystemClock.currentThreadTimeMillis() - 300000, person)
4644 .addMessage("Is it me you're looking for?",
4645 SystemClock.currentThreadTimeMillis(), person)
4646 )
Mady Mellora10448e2019-04-26 13:50:58 -07004647 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -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 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4655 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4656 waitForIdle();
4657
4658 // yes allowed, yes messaging, yes bubble
4659 assertTrue(mService.getNotificationRecord(
4660 sbn.getKey()).getNotification().isBubbleNotification());
4661 }
4662
4663 @Test
4664 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4665 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004666 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004667
4668 // Give it bubble metadata
4669 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4670 // Give it a person
4671 Person person = new Person.Builder()
4672 .setName("bubblebot")
4673 .build();
4674 // Make it a phone call
4675 Notification.Builder nb = new Notification.Builder(mContext,
4676 mTestNotificationChannel.getId())
4677 .setCategory(CATEGORY_CALL)
4678 .addPerson(person)
4679 .setContentTitle("foo")
4680 .setBubbleMetadata(data)
4681 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4682
4683 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4684 nb.build(), new UserHandle(mUid), null, 0);
4685 // Make sure it has foreground service
4686 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4687 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4688
4689 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4690 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4691 waitForIdle();
4692
4693 // yes phone call, yes person, yes foreground service, yes bubble
4694 assertTrue(mService.getNotificationRecord(
4695 sbn.getKey()).getNotification().isBubbleNotification());
4696 }
4697
4698 @Test
4699 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4700 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004701 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004702
4703 // Give it bubble metadata
4704 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4705 // Give it a person
4706 Person person = new Person.Builder()
4707 .setName("bubblebot")
4708 .build();
4709 // Make it a phone call
4710 Notification.Builder nb = new Notification.Builder(mContext,
4711 mTestNotificationChannel.getId())
4712 .setCategory(CATEGORY_CALL)
4713 .addPerson(person)
4714 .setContentTitle("foo")
4715 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004716 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4717
4718 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4719 nb.build(), new UserHandle(mUid), null, 0);
4720 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4721
4722 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4723 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4724 waitForIdle();
4725
Mady Mellorbe797962019-04-01 16:04:24 -07004726 // yes phone call, yes person, NO foreground service, no bubble
4727 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004728 sbn.getKey()).getNotification().isBubbleNotification());
4729 }
4730
4731 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004732 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4733 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004734 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004735
4736 // Give it bubble metadata
4737 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4738 // Make it a phone call
4739 Notification.Builder nb = new Notification.Builder(mContext,
4740 mTestNotificationChannel.getId())
4741 .setCategory(CATEGORY_CALL)
4742 .setContentTitle("foo")
4743 .setBubbleMetadata(data)
4744 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4745
4746 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4747 nb.build(), new UserHandle(mUid), null, 0);
4748 // Make sure it has foreground service
4749 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4750 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4751
4752 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4753 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4754 waitForIdle();
4755
4756 // yes phone call, yes foreground service, BUT NO person, no bubble
4757 assertFalse(mService.getNotificationRecord(
4758 sbn.getKey()).getNotification().isBubbleNotification());
4759 }
4760
4761 @Test
4762 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4763 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004764 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004765
4766 // Give it bubble metadata
4767 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4768 // Give it a person
4769 Person person = new Person.Builder()
4770 .setName("bubblebot")
4771 .build();
4772 // No category
4773 Notification.Builder nb = new Notification.Builder(mContext,
4774 mTestNotificationChannel.getId())
4775 .addPerson(person)
4776 .setContentTitle("foo")
4777 .setBubbleMetadata(data)
4778 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4779
4780 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4781 nb.build(), new UserHandle(mUid), null, 0);
4782 // Make sure it has foreground service
4783 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4784 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4785
4786 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4787 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4788 waitForIdle();
4789
4790 // yes person, yes foreground service, BUT NO call, no bubble
4791 assertFalse(mService.getNotificationRecord(
4792 sbn.getKey()).getNotification().isBubbleNotification());
4793 }
4794
4795 @Test
4796 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004797 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004798 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004799
Mady Mellorbe797962019-04-01 16:04:24 -07004800 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004801 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004802 // Give it a person
4803 Person person = new Person.Builder()
4804 .setName("bubblebot")
4805 .build();
4806 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004807 Notification.Builder nb = new Notification.Builder(mContext,
4808 mTestNotificationChannel.getId())
4809 .setContentTitle("foo")
4810 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004811 .setStyle(new Notification.MessagingStyle(person)
4812 .setConversationTitle("Bubble Chat")
4813 .addMessage("Hello?",
4814 SystemClock.currentThreadTimeMillis() - 300000, person)
4815 .addMessage("Is it me you're looking for?",
4816 SystemClock.currentThreadTimeMillis(), person)
4817 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004818 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4819
4820 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4821 nb.build(), new UserHandle(mUid), null, 0);
4822 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4823
4824 // Post the notification
4825 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4826 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4827 waitForIdle();
4828
4829 // not allowed, no bubble
4830 assertFalse(mService.getNotificationRecord(
4831 sbn.getKey()).getNotification().isBubbleNotification());
4832 }
4833
4834 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004835 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004836 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004837 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004838
4839 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07004840 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004841
4842 // Post the notification
Mady Mellorbe797962019-04-01 16:04:24 -07004843 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004844 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4845 waitForIdle();
4846
4847 // no bubble metadata, no bubble
4848 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07004849 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004850 }
4851
4852 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004853 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004854 // Bubbles are allowed except on this channel
4855 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004856
Mady Mellorbe797962019-04-01 16:04:24 -07004857 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004858 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004859 // Give it a person
4860 Person person = new Person.Builder()
4861 .setName("bubblebot")
4862 .build();
4863 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004864 Notification.Builder nb = new Notification.Builder(mContext,
4865 mTestNotificationChannel.getId())
4866 .setContentTitle("foo")
4867 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004868 .setStyle(new Notification.MessagingStyle(person)
4869 .setConversationTitle("Bubble Chat")
4870 .addMessage("Hello?",
4871 SystemClock.currentThreadTimeMillis() - 300000, person)
4872 .addMessage("Is it me you're looking for?",
4873 SystemClock.currentThreadTimeMillis(), person)
4874 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004875 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4876
4877 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4878 nb.build(), new UserHandle(mUid), null, 0);
4879 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4880
4881 // Post the notification
4882 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4883 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4884 waitForIdle();
4885
4886 // channel not allowed, no bubble
4887 assertFalse(mService.getNotificationRecord(
4888 sbn.getKey()).getNotification().isBubbleNotification());
4889 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004890
Mady Mellor49b1bf12019-03-29 12:00:02 -07004891 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004892 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004893 // Bubbles are not allowed!
4894 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004895
4896 // Give it bubble metadata
4897 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4898 // Give it a person
4899 Person person = new Person.Builder()
4900 .setName("bubblebot")
4901 .build();
4902 // Make it a phone call
4903 Notification.Builder nb = new Notification.Builder(mContext,
4904 mTestNotificationChannel.getId())
4905 .setCategory(CATEGORY_CALL)
4906 .addPerson(person)
4907 .setContentTitle("foo")
4908 .setBubbleMetadata(data)
4909 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4910
4911 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4912 nb.build(), new UserHandle(mUid), null, 0);
4913 // Make sure it has foreground service
4914 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4915 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4916
4917 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4918 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4919 waitForIdle();
4920
4921 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
4922 assertFalse(mService.getNotificationRecord(
4923 sbn.getKey()).getNotification().isBubbleNotification());
4924 }
4925
4926 @Test
4927 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004928 // Bubbles are allowed, but not on channel.
4929 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004930
4931 // Give it bubble metadata
4932 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4933 // Give it a person
4934 Person person = new Person.Builder()
4935 .setName("bubblebot")
4936 .build();
4937 // Make it a phone call
4938 Notification.Builder nb = new Notification.Builder(mContext,
4939 mTestNotificationChannel.getId())
4940 .setCategory(CATEGORY_CALL)
4941 .addPerson(person)
4942 .setContentTitle("foo")
4943 .setBubbleMetadata(data)
4944 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4945
4946 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4947 nb.build(), new UserHandle(mUid), null, 0);
4948 // Make sure it has foreground service
4949 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4950 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4951
4952 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4953 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4954 waitForIdle();
4955
4956 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
4957 assertFalse(mService.getNotificationRecord(
4958 sbn.getKey()).getNotification().isBubbleNotification());
4959 }
4960
4961 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07004962 public void testCancelAllNotifications_cancelsBubble() throws Exception {
4963 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4964 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
4965 mService.addNotification(nr);
4966
4967 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
4968 waitForIdle();
4969
4970 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4971 assertEquals(0, notifs.length);
4972 assertEquals(0, mService.getNotificationRecordCount());
4973 }
4974
4975 @Test
4976 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
4977 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4978 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4979
4980 // Post the notification
4981 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4982 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
4983 waitForIdle();
4984
4985 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4986 assertEquals(1, notifs.length);
4987 assertEquals(1, mService.getNotificationRecordCount());
4988
Julia Reynoldse4a47dd2019-06-07 13:40:59 -04004989 mBinderService.cancelNotificationWithTag(PKG, PKG, null, nrBubble.sbn.getId(),
Mady Mellor49b1bf12019-03-29 12:00:02 -07004990 nrBubble.sbn.getUserId());
4991 waitForIdle();
4992
4993 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4994 assertEquals(0, notifs2.length);
4995 assertEquals(0, mService.getNotificationRecordCount());
4996 }
4997
4998 @Test
4999 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5000 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5001 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5002 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5003
5004 mService.addNotification(nrNormal);
5005 mService.addNotification(nrBubble);
5006
5007 mService.getBinderService().cancelNotificationsFromListener(null, null);
5008 waitForIdle();
5009
5010 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5011 assertEquals(1, notifs.length);
5012 assertEquals(1, mService.getNotificationRecordCount());
5013 }
5014
5015 @Test
5016 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
5017 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5018 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5019 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5020
5021 mService.addNotification(nrNormal);
5022 mService.addNotification(nrBubble);
5023
5024 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
5025 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5026 waitForIdle();
5027
5028 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5029 assertEquals(1, notifs.length);
5030 assertEquals(1, mService.getNotificationRecordCount());
5031 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005032
Julia Reynolds4214da92019-04-10 15:04:06 -04005033 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005034 public void testGetAllowedAssistantAdjustments() throws Exception {
5035 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005036 assertNotNull(capabilities);
5037
5038 for (int i = capabilities.size() - 1; i >= 0; i--) {
5039 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005040 mBinderService.disallowAssistantAdjustment(capability);
5041 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5042 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005043 assertNotNull(currentCapabilities);
5044 assertFalse(currentCapabilities.contains(capability));
5045 }
5046 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005047
Julia Reynolds4214da92019-04-10 15:04:06 -04005048 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005049 public void testAdjustRestrictedKey() throws Exception {
5050 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005051 mService.addNotification(r);
5052 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005053
5054 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5055 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5056
5057 Bundle signals = new Bundle();
5058 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5059 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
5060 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
5061 "", r.getUser().getIdentifier());
5062
5063 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5064 r.applyAdjustments();
5065
5066 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5067 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5068 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005069
Julia Reynolds4214da92019-04-10 15:04:06 -04005070 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005071 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005072 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5073 .thenReturn(true);
5074 mService.setZenHelper(mock(ZenModeHelper.class));
5075 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005076 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5077 boolean isEnabled = true;
5078 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5079 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5080
5081 try {
5082 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005083 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005084 } catch (IllegalArgumentException e) {
5085 // yay
5086 }
5087
5088 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5089 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5090 mBinderService.addAutomaticZenRule(rule);
5091
5092 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5093 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5094 mBinderService.addAutomaticZenRule(rule);
5095 }
5096
Julia Reynolds4214da92019-04-10 15:04:06 -04005097 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005098 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5099 try {
5100 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5101 mUid + UserHandle.PER_USER_RANGE);
5102 fail("Cannot call cross user without permission");
5103 } catch (SecurityException e) {
5104 // pass
5105 }
5106
5107 // cross user, with permission, no problem
5108 TestablePermissions perms = mContext.getTestablePermissions();
5109 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5110 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5111 mUid + UserHandle.PER_USER_RANGE);
5112 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005113
Julia Reynolds4214da92019-04-10 15:04:06 -04005114 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005115 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5116 try {
5117 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5118 mUid + UserHandle.PER_USER_RANGE);
5119 fail("Cannot call cross user without permission");
5120 } catch (SecurityException e) {
5121 // pass
5122 }
5123
5124 // cross user, with permission, no problem
5125 TestablePermissions perms = mContext.getTestablePermissions();
5126 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5127 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5128 mUid + UserHandle.PER_USER_RANGE);
5129 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005130
5131 @Test
5132 public void testNotificationBubbleChanged_false() throws Exception {
5133 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005134 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005135
5136 // Notif with bubble metadata but not our other misc requirements
5137 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5138 null /* tvExtender */, true /* isBubble */);
5139
5140 // Say we're foreground
5141 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5142 IMPORTANCE_FOREGROUND);
5143
5144 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5145 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5146 waitForIdle();
5147
Mady Mellor66efd5e2019-05-15 13:38:11 -07005148 // Reset as this is called when the notif is first sent
5149 reset(mListeners);
5150
Mady Mellora54e9fa2019-04-18 13:26:18 -07005151 // First we were a bubble
5152 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5153 assertEquals(1, notifsBefore.length);
5154 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5155
5156 // Notify we're not a bubble
5157 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5158 waitForIdle();
5159
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005160 // Make sure we are not a bubble
5161 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5162 assertEquals(1, notifsAfter.length);
5163 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005164 }
5165
5166 @Test
5167 public void testNotificationBubbleChanged_true() throws Exception {
5168 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005169 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005170
5171 // Plain notification that has bubble metadata
5172 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5173 null /* tvExtender */, true /* isBubble */);
5174 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5175 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5176 waitForIdle();
5177
5178 // Would be a normal notification because wouldn't have met requirements to bubble
5179 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5180 assertEquals(1, notifsBefore.length);
5181 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5182
5183 // Make the package foreground so that we're allowed to be a bubble
5184 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5185 IMPORTANCE_FOREGROUND);
5186
Mady Mellor66efd5e2019-05-15 13:38:11 -07005187 // Reset as this is called when the notif is first sent
5188 reset(mListeners);
5189
Mady Mellora54e9fa2019-04-18 13:26:18 -07005190 // Notify we are now a bubble
5191 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5192 waitForIdle();
5193
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005194 // Make sure we are a bubble
5195 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5196 assertEquals(1, notifsAfter.length);
5197 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005198 }
5199
5200 @Test
5201 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5202 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005203 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005204
5205 // Notif that is not a bubble
5206 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5207 null /* tvExtender */, true /* isBubble */);
5208 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5209 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5210 waitForIdle();
5211
Mady Mellor66efd5e2019-05-15 13:38:11 -07005212 // Reset as this is called when the notif is first sent
5213 reset(mListeners);
5214
Mady Mellora54e9fa2019-04-18 13:26:18 -07005215 // Would be a normal notification because wouldn't have met requirements to bubble
5216 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5217 assertEquals(1, notifsBefore.length);
5218 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5219
5220 // Notify we are now a bubble
5221 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5222 waitForIdle();
5223
5224 // We still wouldn't be a bubble because the notification didn't meet requirements
5225 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5226 assertEquals(1, notifsAfter.length);
5227 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5228 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005229
5230 @Test
5231 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5232 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005233 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005234
5235 // Plain notification that has bubble metadata
5236 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5237 null /* tvExtender */, true /* isBubble */);
5238 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5239 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5240 waitForIdle();
5241
5242 // Would be a normal notification because wouldn't have met requirements to bubble
5243 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5244 assertEquals(1, notifsBefore.length);
5245 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5246
5247 // Make the package foreground so that we're allowed to be a bubble
5248 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5249 IMPORTANCE_FOREGROUND);
5250
5251 // And we are low ram
5252 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5253
5254 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5255 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5256 assertEquals(1, notifsAfter.length);
5257 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005258 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04005259
5260 @Test
5261 public void testRemoveLargeRemoteViews() throws Exception {
5262 int removeSize = mContext.getResources().getInteger(
5263 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
5264
5265 RemoteViews rv = mock(RemoteViews.class);
5266 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
5267 when(rv.clone()).thenReturn(rv);
5268 RemoteViews rv1 = mock(RemoteViews.class);
5269 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
5270 when(rv1.clone()).thenReturn(rv1);
5271 RemoteViews rv2 = mock(RemoteViews.class);
5272 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
5273 when(rv2.clone()).thenReturn(rv2);
5274 RemoteViews rv3 = mock(RemoteViews.class);
5275 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
5276 when(rv3.clone()).thenReturn(rv3);
5277 RemoteViews rv4 = mock(RemoteViews.class);
5278 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
5279 when(rv4.clone()).thenReturn(rv4);
5280 // note: different!
5281 RemoteViews rv5 = mock(RemoteViews.class);
5282 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
5283 when(rv5.clone()).thenReturn(rv5);
5284
5285 Notification np = new Notification.Builder(mContext, "test")
5286 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5287 .setContentText("test")
5288 .setCustomContentView(rv)
5289 .setCustomBigContentView(rv1)
5290 .setCustomHeadsUpContentView(rv2)
5291 .build();
5292 Notification n = new Notification.Builder(mContext, "test")
5293 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5294 .setContentText("test")
5295 .setCustomContentView(rv3)
5296 .setCustomBigContentView(rv4)
5297 .setCustomHeadsUpContentView(rv5)
5298 .setPublicVersion(np)
5299 .build();
5300
5301 assertNotNull(np.contentView);
5302 assertNotNull(np.bigContentView);
5303 assertNotNull(np.headsUpContentView);
5304
5305 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
5306 assertNotNull(n.publicVersion.contentView);
5307 assertNotNull(n.publicVersion.bigContentView);
5308 assertNotNull(n.publicVersion.headsUpContentView);
5309
5310 mService.fixNotification(n, PKG, "tag", 9, 0);
5311
5312 assertNull(n.contentView);
5313 assertNull(n.bigContentView);
5314 assertNotNull(n.headsUpContentView);
5315 assertNull(n.publicVersion.contentView);
5316 assertNull(n.publicVersion.bigContentView);
5317 assertNull(n.publicVersion.headsUpContentView);
5318
5319 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
5320 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005321}