blob: 0fce618012f953979d73430b3ae82dcdc4a56aa3 [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 Mellor22f2f072019-04-18 13:26:18 -070023import static android.app.Notification.FLAG_AUTO_CANCEL;
Mady Mellor49b1bf12019-03-29 12:00:02 -070024import static android.app.Notification.FLAG_BUBBLE;
Julia Reynoldse5c60452018-04-30 14:41:36 -040025import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050026import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
Julia Reynolds27c0a962018-12-10 12:37:28 -050027import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040028import static android.app.NotificationManager.IMPORTANCE_HIGH;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040029import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050030import static android.app.NotificationManager.IMPORTANCE_MAX;
Julia Reynolds4da79702017-06-01 11:06:10 -040031import static android.app.NotificationManager.IMPORTANCE_NONE;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040032import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050033import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
34import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
35import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
36import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
37import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
38import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
39import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
40import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
41import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
Julia Reynoldse1816412017-10-24 10:39:11 -040042import static android.content.pm.PackageManager.FEATURE_WATCH;
Julia Reynolds4db59552017-06-30 13:34:01 -040043import static android.content.pm.PackageManager.PERMISSION_DENIED;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -040044import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050045import static android.os.Build.VERSION_CODES.O_MR1;
46import static android.os.Build.VERSION_CODES.P;
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -040047import static android.service.notification.Adjustment.KEY_IMPORTANCE;
48import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
Tony Makeda84a72018-11-19 17:01:32 +000049import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
50import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040051
Geoffrey Pitsch03533712017-01-05 10:30:07 -050052import static junit.framework.Assert.assertEquals;
Julia Reynolds727a7282017-04-13 10:54:01 -040053import static junit.framework.Assert.assertFalse;
Julia Reynolds92febc32017-10-26 11:30:31 -040054import static junit.framework.Assert.assertNotNull;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040055import static junit.framework.Assert.assertNull;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050056import static junit.framework.Assert.assertTrue;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050057import static junit.framework.Assert.fail;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050058
Julia Reynolds5f20e9f2017-01-30 08:54:53 -050059import static org.mockito.Matchers.anyBoolean;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -040060import static org.mockito.Matchers.anyLong;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050061import static org.mockito.Matchers.anyString;
62import static org.mockito.Matchers.eq;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050063import static org.mockito.Mockito.any;
64import static org.mockito.Mockito.anyInt;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040065import static org.mockito.Mockito.doAnswer;
Julia Reynolds4afe2642019-05-01 08:42:24 -040066import static org.mockito.Mockito.doNothing;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050067import static org.mockito.Mockito.mock;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040068import static org.mockito.Mockito.never;
69import static org.mockito.Mockito.reset;
Julia Reynolds503ed942017-10-04 16:04:56 -040070import static org.mockito.Mockito.spy;
71import static org.mockito.Mockito.timeout;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050072import static org.mockito.Mockito.times;
73import static org.mockito.Mockito.verify;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050074import static org.mockito.Mockito.when;
75
Julia Reynolds68263d12017-06-21 14:21:19 -040076import android.app.ActivityManager;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -040077import android.app.AppOpsManager;
Julia Reynoldsa94365d2019-04-09 10:48:43 -040078import android.app.AutomaticZenRule;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040079import android.app.IActivityManager;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050080import android.app.INotificationManager;
Julia Reynolds268647a2018-10-25 16:54:27 -040081import android.app.ITransientNotification;
82import android.app.IUriGrantsManager;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050083import android.app.Notification;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040084import android.app.Notification.MessagingStyle.Message;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050085import android.app.NotificationChannel;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040086import android.app.NotificationChannelGroup;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050087import android.app.NotificationManager;
Mady Mellor7eb18ef2019-03-27 14:03:46 -070088import android.app.PendingIntent;
Mady Mellorbe797962019-04-01 16:04:24 -070089import android.app.Person;
Mady Mellora10448e2019-04-26 13:50:58 -070090import android.app.RemoteInput;
Jason Parks50322ff2018-03-27 10:23:33 -050091import android.app.admin.DevicePolicyManagerInternal;
Julia Reynolds7217dc92018-03-07 12:12:09 -050092import android.app.usage.UsageStatsManagerInternal;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040093import android.companion.ICompanionDeviceManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -050094import android.content.ComponentName;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -060095import android.content.ContentUris;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050096import android.content.Context;
Beverlyd4f96492017-08-02 13:36:11 -040097import android.content.Intent;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050098import android.content.pm.ApplicationInfo;
99import android.content.pm.IPackageManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500100import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500101import android.content.pm.ParceledListSlice;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400102import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200103import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400104import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700105import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400106import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400107import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500108import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400109import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400110import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400111import android.os.IBinder;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400112import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400113import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700114import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500115import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400116import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000117import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600118import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000119import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400120import android.service.notification.Adjustment;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400121import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400122import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500123import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400124import android.service.notification.ZenPolicy;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400125import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400126import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400127import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400128import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400129import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400130import android.testing.TestablePermissions;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400131import android.text.Html;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400132import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000133import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400134import android.util.AtomicFile;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400135
Mady Mellor49b1bf12019-03-29 12:00:02 -0700136import androidx.annotation.Nullable;
137import androidx.test.InstrumentationRegistry;
138
Kristian Monsen05f34792018-04-09 10:27:16 +0200139import com.android.internal.R;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000140import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Julia Reynolds503ed942017-10-04 16:04:56 -0400141import com.android.internal.statusbar.NotificationVisibility;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700142import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400143import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500144import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400145import com.android.server.lights.Light;
146import com.android.server.lights.LightsManager;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400147import com.android.server.notification.NotificationManagerService.NotificationAssistants;
148import com.android.server.notification.NotificationManagerService.NotificationListeners;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700149import com.android.server.uri.UriGrantsManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400150import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400151
152import org.junit.After;
153import org.junit.Before;
154import org.junit.Test;
155import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500156import org.mockito.ArgumentCaptor;
157import org.mockito.Mock;
158import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400159import org.mockito.stubbing.Answer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500160
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400161import java.io.BufferedInputStream;
162import java.io.ByteArrayInputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400163import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400164import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400165import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500166import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000167import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400168import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400169import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200170import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500171
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400172@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400173@RunWith(AndroidTestingRunner.class)
174@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500175public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500176 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000177 private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
178 "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
179 + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
180 private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD =
181 "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
182 + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
183
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400184 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500185 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500186 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400187 private NotificationManagerInternal mInternalService;
Julia Reynoldsda781472017-04-12 09:41:16 -0400188 @Mock
189 private IPackageManager mPackageManager;
190 @Mock
191 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400192 @Mock
193 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400194 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500195 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400196 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400197 @Mock
198 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400199 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400200 AtomicFile mPolicyFile;
201 File mFile;
202 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400203 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400204 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400205 private UsageStatsManagerInternal mAppUsageStats;
206 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400207 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400208 @Mock
209 ActivityManager mActivityManager;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400210 NotificationManagerService.WorkerHandler mHandler;
Kristian Monsen05f34792018-04-09 10:27:16 +0200211 @Mock
212 Resources mResources;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400213
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500214 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500215 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000216
217 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
218
Julia Reynoldsda781472017-04-12 09:41:16 -0400219 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400220 private NotificationListeners mListeners;
221 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400222 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400223 private ManagedServices.ManagedServiceInfo mListener;
224 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400225 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400226 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400227 @Mock
228 IBinder mPermOwner;
229 @Mock
230 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700231 @Mock
232 IUriGrantsManager mUgm;
233 @Mock
234 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400235 @Mock
236 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000237 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000238 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
239 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400240 @Mock
241 UserManager mUm;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500242
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400243 // Use a Testable subclass so we can simulate calls from the system without failing.
244 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500245 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700246 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000247 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000248 @Nullable
249 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500250
Julia Reynolds0c245002019-03-27 16:10:11 -0400251 TestableNotificationManagerService(Context context) {
Amith Yamasani803eab692017-11-09 17:47:04 -0800252 super(context);
253 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400254
255 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400256 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500257 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700258 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400259 }
260
261 @Override
262 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500263 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700264 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400265 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400266
267 @Override
268 protected ICompanionDeviceManager getCompanionManager() {
269 return null;
270 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800271
272 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800273 protected void reportUserInteraction(NotificationRecord r) {
274 return;
275 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500276
277 @Override
278 protected void handleSavePolicyFile() {
279 return;
280 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000281
282 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000283 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
284 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000285 countLogSmartSuggestionsVisible++;
286 }
287
Annie Meng8b646fd2019-02-01 18:46:42 +0000288 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000289 protected void setNotificationAssistantAccessGrantedForUserInternal(
290 ComponentName assistant, int userId, boolean granted) {
291 if (mNotificationAssistantAccessGrantedCallback != null) {
292 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
293 return;
294 }
295 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
296 }
297
298 private void setNotificationAssistantAccessGrantedCallback(
299 @Nullable NotificationAssistantAccessGrantedCallback callback) {
300 this.mNotificationAssistantAccessGrantedCallback = callback;
301 }
302
303 interface NotificationAssistantAccessGrantedCallback {
304 void onGranted(ComponentName assistant, int userId, boolean granted);
305 }
306
Mady Mellorca0c24c2019-05-16 16:14:32 -0700307 @Override
308 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
309 String packageName) {
310 // Tests for this not being true are in CTS NotificationManagerTest
311 return true;
312 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400313 }
314
Beverly58b24532018-10-02 09:08:23 -0400315 private class TestableToastCallback extends ITransientNotification.Stub {
316 @Override
317 public void show(IBinder windowToken) {
318 }
319
320 @Override
321 public void hide() {
322 }
323 }
324
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500325 @Before
326 public void setUp() throws Exception {
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000327 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
328 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
329
Julia Reynoldsda781472017-04-12 09:41:16 -0400330 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400331
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700332 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
333 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400334 LocalServices.removeServiceForTest(WindowManagerInternal.class);
335 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700336
Julia Reynolds4afe2642019-05-01 08:42:24 -0400337 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
338
Julia Reynolds0c245002019-03-27 16:10:11 -0400339 mService = new TestableNotificationManagerService(mContext);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500340
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400341 // Use this testable looper.
342 mTestableLooper = TestableLooper.get(this);
Julia Reynolds503ed942017-10-04 16:04:56 -0400343 mHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500344 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400345 mContext.setMockPackageManager(mPackageManagerClient);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500346 final ApplicationInfo applicationInfo = new ApplicationInfo();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400347 applicationInfo.uid = mUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400348 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500349 .thenReturn(applicationInfo);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500350 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500351 .thenReturn(applicationInfo);
Julia Reynolds92febc32017-10-26 11:30:31 -0400352 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500353 final LightsManager mockLightsManager = mock(LightsManager.class);
354 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400355 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400356 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700357 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400358 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400359 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400360 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500361
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400362 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400363 mFile = new File(mContext.getCacheDir(), "test.xml");
364 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400365 final String preupgradeXml = "<notification-policy></notification-policy>";
366 mPolicyFile = new AtomicFile(mFile);
367 FileOutputStream fos = mPolicyFile.startWrite();
368 fos.write(preupgradeXml.getBytes());
369 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400370
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400371 // Setup managed services
372 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400373 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400374 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
375 ManagedServices.Config listenerConfig = new ManagedServices.Config();
376 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
377 when(mListeners.getConfig()).thenReturn(listenerConfig);
378 ManagedServices.Config assistantConfig = new ManagedServices.Config();
379 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
380 when(mAssistants.getConfig()).thenReturn(assistantConfig);
381 ManagedServices.Config dndConfig = new ManagedServices.Config();
382 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
383 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
384
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400385 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
386
Julia Reynolds4afe2642019-05-01 08:42:24 -0400387
388 mService.init(mTestableLooper.getLooper(),
389 mPackageManager, mPackageManagerClient, mockLightsManager,
390 mListeners, mAssistants, mConditionProviders,
391 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
392 mGroupHelper, mAm, mAppUsageStats,
393 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
394 mAppOpsManager, mUm);
395 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
396
Julia Reynolds503ed942017-10-04 16:04:56 -0400397 mService.setAudioManager(mAudioManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500398
399 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400400 mBinderService = mService.getBinderService();
401 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500402
403 mBinderService.createNotificationChannels(
404 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400405 assertNotNull(mBinderService.getNotificationChannel(
406 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500407 }
408
Julia Reynoldsb852e562017-06-06 16:14:18 -0400409 @After
410 public void tearDown() throws Exception {
411 mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000412 clearDeviceConfig();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000413 InstrumentationRegistry.getInstrumentation()
414 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400415 }
416
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500417 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400418 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500419 }
420
Mady Mellorc6820342019-05-20 12:04:36 -0700421 private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
422 boolean channelEnabled) {
423 mService.setPreferencesHelper(mPreferencesHelper);
Lyn Han4463f842019-07-09 15:27:28 -0700424 when(mPreferencesHelper.bubblesEnabled()).thenReturn(globalEnabled);
Mady Mellorc6820342019-05-20 12:04:36 -0700425 when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
426 when(mPreferencesHelper.getNotificationChannel(
427 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
428 mTestNotificationChannel);
429 when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
430 mTestNotificationChannel.getImportance());
431 mTestNotificationChannel.setAllowBubbles(channelEnabled);
432 }
433
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500434 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
435 Notification.Builder nb = new Notification.Builder(mContext, "a")
436 .setContentTitle("foo")
437 .setSmallIcon(android.R.drawable.sym_def_app_icon);
438 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0,
439 nb.build(), new UserHandle(userId), null, postTime);
440 return sbn;
441 }
442
Mady Mellor22f2f072019-04-18 13:26:18 -0700443
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400444 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
445 String groupKey, boolean isSummary) {
Mady Mellor22f2f072019-04-18 13:26:18 -0700446 return generateNotificationRecord(channel, id, groupKey, isSummary, false /* isBubble */);
447 }
448
449 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
450 String groupKey, boolean isSummary, boolean isBubble) {
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400451 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
452 .setContentTitle("foo")
453 .setSmallIcon(android.R.drawable.sym_def_app_icon)
454 .setGroup(groupKey)
455 .setGroupSummary(isSummary);
Mady Mellor22f2f072019-04-18 13:26:18 -0700456 if (isBubble) {
457 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
458 }
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400459 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
460 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000461 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400462 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400463
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500464 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500465 return generateNotificationRecord(channel, null);
466 }
467
468 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
469 Notification.TvExtender extender) {
Mady Mellorbe797962019-04-01 16:04:24 -0700470 return generateNotificationRecord(channel, extender, false /* isBubble */);
471 }
472
473 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
474 Notification.TvExtender extender, boolean isBubble) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500475 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500476 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500477 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500478 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500479 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500480 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500481 if (extender != null) {
482 nb.extend(extender);
483 }
Mady Mellorbe797962019-04-01 16:04:24 -0700484 if (isBubble) {
485 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
486 }
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400487 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
488 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000489 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500490 }
491
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400492 private Map<String, Answer> getSignalExtractorSideEffects() {
493 Map<String, Answer> answers = new ArrayMap<>();
494
495 answers.put("override group key", invocationOnMock -> {
496 ((NotificationRecord) invocationOnMock.getArguments()[0])
497 .setOverrideGroupKey("bananas");
498 return null;
499 });
500 answers.put("override people", invocationOnMock -> {
501 ((NotificationRecord) invocationOnMock.getArguments()[0])
502 .setPeopleOverride(new ArrayList<>());
503 return null;
504 });
505 answers.put("snooze criteria", invocationOnMock -> {
506 ((NotificationRecord) invocationOnMock.getArguments()[0])
507 .setSnoozeCriteria(new ArrayList<>());
508 return null;
509 });
510 answers.put("notification channel", invocationOnMock -> {
511 ((NotificationRecord) invocationOnMock.getArguments()[0])
512 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
513 return null;
514 });
515 answers.put("badging", invocationOnMock -> {
516 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
517 r.setShowBadge(!r.canShowBadge());
518 return null;
519 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500520 answers.put("bubbles", invocationOnMock -> {
521 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
522 r.setAllowBubble(!r.canBubble());
523 return null;
524 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400525 answers.put("package visibility", invocationOnMock -> {
526 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
527 Notification.VISIBILITY_SECRET);
528 return null;
529 });
530
531 return answers;
532 }
533
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400534 private void clearDeviceConfig() {
535 DeviceConfig.resetToDefaults(
536 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
537 }
538
539 private void setDefaultAssistantInDeviceConfig(String componentName) {
540 DeviceConfig.setProperty(
541 DeviceConfig.NAMESPACE_SYSTEMUI,
542 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
543 componentName,
544 false);
545 }
546
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700547 private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() {
548 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
549 return new Notification.BubbleMetadata.Builder()
550 .setIntent(pi)
551 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
552 }
553
Mady Mellor22f2f072019-04-18 13:26:18 -0700554 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
555 throws RemoteException {
556
557 // Notification that has bubble metadata
558 NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel, 1,
559 "BUBBLE_GROUP", false /* isSummary */, true /* isBubble */);
560
561 // Make the package foreground so that we're allowed to be a bubble
562 when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn(
563 IMPORTANCE_FOREGROUND);
564
565 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
566 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
567 waitForIdle();
568
569 // Make sure we are a bubble
570 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
571 assertEquals(1, notifsAfter.length);
572 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
573
574 // Plain notification without bubble metadata
575 NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2,
576 "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */);
577 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
578 nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId());
579 waitForIdle();
580
581 notifsAfter = mBinderService.getActiveNotifications(PKG);
582 assertEquals(2, notifsAfter.length);
583
584 // Summary notification for both of those
585 NotificationRecord nrSummary = generateNotificationRecord(mTestNotificationChannel, 3,
586 "BUBBLE_GROUP", true /* isSummary */, false /* isBubble */);
587 if (summaryAutoCancel) {
588 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
589 }
590 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
591 nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId());
592 waitForIdle();
593
594 notifsAfter = mBinderService.getActiveNotifications(PKG);
595 assertEquals(3, notifsAfter.length);
596
597 return nrSummary;
598 }
599
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500600 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500601 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500602 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500603 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400604 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500605 new ParceledListSlice(Arrays.asList(channel)));
606 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400607 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500608 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500609 }
610
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500611 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500612 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500613 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400614 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200615 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500616 fail("Exception should be thrown immediately.");
617 } catch (NullPointerException e) {
618 // pass
619 }
620 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500621
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500622 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500623 public void testCreateNotificationChannels_TwoChannels() throws Exception {
624 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500625 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500626 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500627 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400628 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500629 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400630 assertTrue(mBinderService.getNotificationChannel(
631 PKG, mContext.getUserId(), PKG, "id1") != null);
632 assertTrue(mBinderService.getNotificationChannel(
633 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500634 }
635
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500636 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400637 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
638 throws Exception {
639 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500640 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400641 mBinderService.createNotificationChannels(PKG,
642 new ParceledListSlice(Arrays.asList(channel)));
643
644 // Recreating the channel doesn't throw, but ignores importance.
645 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400646 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400647 mBinderService.createNotificationChannels(PKG,
648 new ParceledListSlice(Arrays.asList(dupeChannel)));
649 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400650 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500651 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400652 }
653
654 @Test
655 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
656 throws Exception {
657 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500658 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400659 mBinderService.createNotificationChannels(PKG,
660 new ParceledListSlice(Arrays.asList(channel)));
661
662 // Recreating with a lower importance is allowed to modify the channel.
663 final NotificationChannel dupeChannel =
664 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
665 mBinderService.createNotificationChannels(PKG,
666 new ParceledListSlice(Arrays.asList(dupeChannel)));
667 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400668 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400669 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
670 }
671
672 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400673 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
674 throws Exception {
675 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500676 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400677 mBinderService.createNotificationChannels(PKG,
678 new ParceledListSlice(Arrays.asList(channel)));
679
680 // The user modifies importance directly, can no longer be changed by the app.
681 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400682 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400683 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
684
685 // Recreating with a lower importance leaves channel unchanged.
686 final NotificationChannel dupeChannel =
687 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
688 mBinderService.createNotificationChannels(PKG,
689 new ParceledListSlice(Arrays.asList(dupeChannel)));
690 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400691 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400692 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400693 }
694
695 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500696 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
697 throws Exception {
698 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500699 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500700 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400701 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400702 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500703 new ParceledListSlice(Arrays.asList(channel1, channel2)));
704 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400705 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500706 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500707 }
708
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500709 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500710 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500711 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
712
713 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400714 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500715 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400716
717 // isBlocked is only used for user blocking, not app suspension
718 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500719 }
720
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500721 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500722 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500723 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
724
725 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400726 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500727 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400728 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400729 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400730
731 mBinderService.createNotificationChannels(
732 PKG, new ParceledListSlice(Arrays.asList(channel)));
733 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400734 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400735 sbn.getId(), sbn.getNotification(), sbn.getUserId());
736 waitForIdle();
737 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
738 }
739
740 @Test
741 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
742 throws Exception {
743 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
744
745 NotificationChannel channel = new NotificationChannel("blocked", "name",
746 NotificationManager.IMPORTANCE_NONE);
747 mBinderService.createNotificationChannels(
748 PKG, new ParceledListSlice(Arrays.asList(channel)));
749
750 final 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();
755 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
756 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400757 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400758 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
759 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400760 }
761
762 @Test
763 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
764 throws Exception {
765 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
766
767 NotificationChannel channel =
768 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
769 mBinderService.createNotificationChannels(
770 PKG, new ParceledListSlice(Arrays.asList(channel)));
771
772 NotificationChannel update =
773 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
774 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
775 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400776 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
777 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400778
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700779 StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400780 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400781 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400782 sbn.getId(), sbn.getNotification(), sbn.getUserId());
783 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700784 // The first time a foreground service notification is shown, we allow the channel
785 // to be updated to allow it to be seen.
786 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
787 assertEquals(IMPORTANCE_LOW,
788 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400789 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
790 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700791 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
792 waitForIdle();
793
794 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
795 update.setFgServiceShown(true);
796 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
797 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400798 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
799 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700800
801 sbn = generateNotificationRecord(channel).sbn;
802 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400803 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700804 sbn.getId(), sbn.getNotification(), sbn.getUserId());
805 waitForIdle();
806 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400807 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400808 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400809 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
810 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500811 }
812
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500813 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -0400814 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
815 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400816 mService.setPreferencesHelper(mPreferencesHelper);
817 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400818
819 NotificationChannel channel = new NotificationChannel("id", "name",
820 NotificationManager.IMPORTANCE_HIGH);
821 channel.setGroup("something");
822 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400823 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -0400824 verify(mUsageStats, times(1)).registerBlocked(eq(r));
825 }
826
827 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -0400828 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500829 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
830
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400831 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -0400832
833 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400834 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds4da79702017-06-01 11:06:10 -0400835 sbn.getId(), sbn.getNotification(), sbn.getUserId());
836 waitForIdle();
837 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500838 }
839
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500840 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400841 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
842 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
843
844 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
845
846 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400847 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400848 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400849 sbn.getId(), sbn.getNotification(), sbn.getUserId());
850 waitForIdle();
851 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400852 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400853 }
854
Brad Stenning8c991ea2018-07-31 13:33:01 -0700855 /**
856 * Confirm the system user on automotive devices can use car categories
857 */
858 @Test
859 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
860 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
861 .thenReturn(true);
862 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
863 Notification.CATEGORY_CAR_WARNING,
864 Notification.CATEGORY_CAR_INFORMATION);
865 int id = 0;
866 for (String category: categories) {
867 final StatusBarNotification sbn =
868 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
869 sbn.getNotification().category = category;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400870 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700871 sbn.getId(), sbn.getNotification(), sbn.getUserId());
872 }
873 waitForIdle();
874 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
875 }
876
877
878 /**
879 * Confirm restricted notification categories only apply to automotive.
880 */
881 @Test
882 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
883 mService.isSystemUid = false;
884 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
885 .thenReturn(false);
886 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
887 Notification.CATEGORY_CAR_WARNING,
888 Notification.CATEGORY_CAR_INFORMATION);
889 int id = 0;
890 for (String category: categories) {
891 final StatusBarNotification sbn =
892 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
893 sbn.getNotification().category = category;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400894 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700895 sbn.getId(), sbn.getNotification(), sbn.getUserId());
896 }
897 waitForIdle();
898 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
899 }
900
901 /**
902 * Confirm if a non-system user tries to use the car categories on a automotive device that
903 * they will get a security exception
904 */
905 @Test
906 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
907 mService.isSystemUid = false;
908 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
909 .thenReturn(true);
910 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
911 Notification.CATEGORY_CAR_WARNING,
912 Notification.CATEGORY_CAR_INFORMATION);
913 for (String category: categories) {
914 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
915 sbn.getNotification().category = category;
916 try {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400917 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700918 sbn.getId(), sbn.getNotification(), sbn.getUserId());
919 fail("Calls from non system apps should not allow use of restricted categories");
920 } catch (SecurityException e) {
921 // pass
922 }
923 }
924 waitForIdle();
925 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
926 }
927
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400928 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400929 public void testBlockedNotifications_blockedByAssistant() throws Exception {
930 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500931 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400932
933 NotificationChannel channel = new NotificationChannel("id", "name",
934 NotificationManager.IMPORTANCE_HIGH);
935 NotificationRecord r = generateNotificationRecord(channel);
936 mService.addEnqueuedNotification(r);
937
Julia Reynolds27c0a962018-12-10 12:37:28 -0500938 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400939 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500940 Adjustment adjustment = new Adjustment(
941 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
942 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400943
944 NotificationManagerService.PostNotificationRunnable runnable =
945 mService.new PostNotificationRunnable(r.getKey());
946 runnable.run();
947 waitForIdle();
948
949 verify(mUsageStats, never()).registerPostedByApp(any());
950 }
951
952 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500953 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400954 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400955 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500956 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -0400957 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500958 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400959 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500960 }
961
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500962 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500963 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400964 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400965 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500966 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500967 waitForIdle();
968 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500969 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500970 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400971 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500972 }
973
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500974 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500975 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400976 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400977 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500978 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400979 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400980 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500981 mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500982 waitForIdle();
983 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500984 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500985 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400986 assertEquals(0, mService.getNotificationRecordCount());
987 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
988 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
989 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -0500990 }
991
992 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500993 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -0400994 NotificationRecord r = generateNotificationRecord(null);
995 final StatusBarNotification sbn = r.sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400996 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -0400997 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500998 mBinderService.cancelNotificationsFromListener(null, null);
999 waitForIdle();
1000 StatusBarNotification[] notifs =
1001 mBinderService.getActiveNotifications(sbn.getPackageName());
1002 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001003 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001004 }
1005
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001006 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001007 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
1008 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001009 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001010 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001011 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001012 waitForIdle();
1013 StatusBarNotification[] notifs =
1014 mBinderService.getActiveNotifications(sbn.getPackageName());
1015 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001016 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001017 }
1018
1019 @Test
Evan Laird05597642019-08-05 17:11:54 -04001020 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1021 throws Exception {
1022 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1023 sbn.getNotification().flags =
1024 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1025 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1026 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1027 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
1028 waitForIdle();
1029 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1030 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1031 }
1032
1033 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001034 public void testUserInitiatedClearAll_noLeak() throws Exception {
1035 final NotificationRecord n = generateNotificationRecord(
1036 mTestNotificationChannel, 1, "group", true);
1037
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001038 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001039 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
1040 waitForIdle();
1041
Julia Reynolds503ed942017-10-04 16:04:56 -04001042 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001043 n.getUserId());
1044 waitForIdle();
1045 StatusBarNotification[] notifs =
1046 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1047 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001048 assertEquals(0, mService.getNotificationRecordCount());
1049 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1050 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1051 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001052 }
1053
1054 @Test
1055 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1056 final NotificationRecord parent = generateNotificationRecord(
1057 mTestNotificationChannel, 1, "group1", true);
1058 final NotificationRecord child = generateNotificationRecord(
1059 mTestNotificationChannel, 2, "group1", false);
1060
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001061 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001062 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001063 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001064 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1065 waitForIdle();
1066
1067 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1068 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001069 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001070 }
1071
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001072 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001073 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1074 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1075 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001076 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001077 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1078 }
1079 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1080 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001081
Julia Reynolds503ed942017-10-04 16:04:56 -04001082 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001083 }
1084
1085 @Test
1086 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1087 final NotificationRecord parent = generateNotificationRecord(
1088 mTestNotificationChannel, 1, "group1", true);
1089 final NotificationRecord parentAsChild = generateNotificationRecord(
1090 mTestNotificationChannel, 1, "group1", false);
1091 final NotificationRecord child = generateNotificationRecord(
1092 mTestNotificationChannel, 2, "group1", false);
1093
1094 // fully post parent notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001095 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001096 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1097 waitForIdle();
1098
1099 // enqueue the child several times
1100 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001101 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001102 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1103 }
1104 // make the parent a child, which will cancel the child notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001105 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001106 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1107 parentAsChild.sbn.getUserId());
1108 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001109
Julia Reynolds503ed942017-10-04 16:04:56 -04001110 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001111 }
1112
1113 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001114 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1115 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001116 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001117 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001118 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001119 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001120 waitForIdle();
1121 StatusBarNotification[] notifs =
1122 mBinderService.getActiveNotifications(sbn.getPackageName());
1123 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001124 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001125 }
1126
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001127 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001128 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1129 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001130 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001131 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001132 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001133 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1134 waitForIdle();
1135 StatusBarNotification[] notifs =
1136 mBinderService.getActiveNotifications(sbn.getPackageName());
1137 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001138 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001139 }
1140
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001141 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001142 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1143 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001144 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001145 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001146 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1147 waitForIdle();
1148 StatusBarNotification[] notifs =
1149 mBinderService.getActiveNotifications(sbn.getPackageName());
1150 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001151 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001152 }
1153
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001154 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001155 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1156 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001157 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001158 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001159 // Null pkg is how we signal a user switch.
1160 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1161 waitForIdle();
1162 StatusBarNotification[] notifs =
1163 mBinderService.getActiveNotifications(sbn.getPackageName());
1164 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001165 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001166 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001167
1168 @Test
Beverly40239d92017-07-07 10:20:41 -04001169 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1170 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1171 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001172 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Beverly40239d92017-07-07 10:20:41 -04001173 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1174 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1175 waitForIdle();
1176 StatusBarNotification[] notifs =
1177 mBinderService.getActiveNotifications(sbn.getPackageName());
1178 assertEquals(0, notifs.length);
1179 }
1180
1181 @Test
1182 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1183 final NotificationRecord notif = generateNotificationRecord(
1184 mTestNotificationChannel, 1, "group", true);
1185 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001186 mService.addNotification(notif);
1187 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001188 notif.getUserId(), 0, null);
1189 waitForIdle();
1190 StatusBarNotification[] notifs =
1191 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1192 assertEquals(0, notifs.length);
1193 }
1194
1195 @Test
1196 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1197 final NotificationRecord notif = generateNotificationRecord(
1198 mTestNotificationChannel, 1, "group", true);
1199 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001200 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001201
Julia Reynolds503ed942017-10-04 16:04:56 -04001202 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001203 notif.getUserId());
1204 waitForIdle();
1205 StatusBarNotification[] notifs =
1206 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1207 assertEquals(1, notifs.length);
1208 }
1209
1210 @Test
1211 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1212 final NotificationRecord parent = generateNotificationRecord(
1213 mTestNotificationChannel, 1, "group", true);
1214 final NotificationRecord child = generateNotificationRecord(
1215 mTestNotificationChannel, 2, "group", false);
1216 final NotificationRecord child2 = generateNotificationRecord(
1217 mTestNotificationChannel, 3, "group", false);
1218 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1219 final NotificationRecord newGroup = generateNotificationRecord(
1220 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001221 mService.addNotification(parent);
1222 mService.addNotification(child);
1223 mService.addNotification(child2);
1224 mService.addNotification(newGroup);
1225 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001226 waitForIdle();
1227 StatusBarNotification[] notifs =
1228 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1229 assertEquals(1, notifs.length);
1230 }
1231
1232 @Test
1233 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1234 final NotificationRecord parent = generateNotificationRecord(
1235 mTestNotificationChannel, 1, "group", true);
1236 final NotificationRecord child = generateNotificationRecord(
1237 mTestNotificationChannel, 2, "group", false);
1238 final NotificationRecord child2 = generateNotificationRecord(
1239 mTestNotificationChannel, 3, "group", false);
1240 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1241 final NotificationRecord newGroup = generateNotificationRecord(
1242 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001243 mService.addNotification(parent);
1244 mService.addNotification(child);
1245 mService.addNotification(child2);
1246 mService.addNotification(newGroup);
1247 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001248 parent.getUserId());
1249 waitForIdle();
1250 StatusBarNotification[] notifs =
1251 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1252 assertEquals(1, notifs.length);
1253 }
1254
1255 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001256 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
1257 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001258 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001259 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001260 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001261 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1262 sbn.getUserId());
1263 waitForIdle();
1264 StatusBarNotification[] notifs =
1265 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001266 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001267 }
1268
1269 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001270 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1271 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1272 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001273 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001274 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001275 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1276 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001277 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001278 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1279 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
1280 waitForIdle();
1281 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001282 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001283 }
1284
1285 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001286 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1287 throws Exception {
1288 final NotificationRecord parent = generateNotificationRecord(
1289 mTestNotificationChannel, 1, "group", true);
1290 final NotificationRecord child = generateNotificationRecord(
1291 mTestNotificationChannel, 2, "group", false);
1292 final NotificationRecord child2 = generateNotificationRecord(
1293 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001294 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001295 final NotificationRecord newGroup = generateNotificationRecord(
1296 mTestNotificationChannel, 4, "group2", false);
1297 mService.addNotification(parent);
1298 mService.addNotification(child);
1299 mService.addNotification(child2);
1300 mService.addNotification(newGroup);
1301 mService.getBinderService().cancelNotificationsFromListener(null, null);
1302 waitForIdle();
1303 StatusBarNotification[] notifs =
1304 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1305 assertEquals(0, notifs.length);
1306 }
1307
1308 @Test
1309 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1310 throws Exception {
1311 final NotificationRecord parent = generateNotificationRecord(
1312 mTestNotificationChannel, 1, "group", true);
1313 final NotificationRecord child = generateNotificationRecord(
1314 mTestNotificationChannel, 2, "group", false);
1315 final NotificationRecord child2 = generateNotificationRecord(
1316 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001317 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001318 final NotificationRecord newGroup = generateNotificationRecord(
1319 mTestNotificationChannel, 4, "group2", false);
1320 mService.addNotification(parent);
1321 mService.addNotification(child);
1322 mService.addNotification(child2);
1323 mService.addNotification(newGroup);
1324 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1325 child2.sbn.getKey(), newGroup.sbn.getKey()};
1326 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1327 waitForIdle();
1328 StatusBarNotification[] notifs =
1329 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1330 assertEquals(1, notifs.length);
1331 }
1332
1333 @Test
1334 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1335 final NotificationRecord parent = generateNotificationRecord(
1336 mTestNotificationChannel, 1, "group", true);
1337 final NotificationRecord child = generateNotificationRecord(
1338 mTestNotificationChannel, 2, "group", false);
1339 final NotificationRecord child2 = generateNotificationRecord(
1340 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001341 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001342 final NotificationRecord newGroup = generateNotificationRecord(
1343 mTestNotificationChannel, 4, "group2", false);
1344 mService.addNotification(parent);
1345 mService.addNotification(child);
1346 mService.addNotification(child2);
1347 mService.addNotification(newGroup);
1348 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1349 parent.getUserId());
1350 waitForIdle();
1351 StatusBarNotification[] notifs =
1352 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1353 assertEquals(0, notifs.length);
1354 }
1355
1356 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001357 public void testFindGroupNotificationsLocked() throws Exception {
1358 // make sure the same notification can be found in both lists and returned
1359 final NotificationRecord group1 = generateNotificationRecord(
1360 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001361 mService.addEnqueuedNotification(group1);
1362 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001363
1364 // should not be returned
1365 final NotificationRecord group2 = generateNotificationRecord(
1366 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001367 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001368 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1369 waitForIdle();
1370
1371 // should not be returned
1372 final NotificationRecord nonGroup = generateNotificationRecord(
1373 mTestNotificationChannel, 3, null, false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001374 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001375 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1376 waitForIdle();
1377
1378 // same group, child, should be returned
1379 final NotificationRecord group1Child = generateNotificationRecord(
1380 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001381 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001382 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1383 waitForIdle();
1384
1385 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001386 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001387 group1.sbn.getUserId());
1388 assertEquals(3, inGroup1.size());
1389 for (NotificationRecord record : inGroup1) {
1390 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1391 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1392 }
1393 }
1394
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001395 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001396 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1397 final NotificationRecord notif = generateNotificationRecord(
1398 mTestNotificationChannel, 1, "group", true);
1399 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1400 mService.addNotification(notif);
1401 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1402 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1403 waitForIdle();
1404 StatusBarNotification[] notifs =
1405 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1406 assertEquals(0, notifs.length);
1407 }
1408
1409 @Test
1410 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1411 throws Exception {
1412 final NotificationRecord parent = generateNotificationRecord(
1413 mTestNotificationChannel, 1, "group", true);
1414 final NotificationRecord child = generateNotificationRecord(
1415 mTestNotificationChannel, 2, "group", false);
1416 final NotificationRecord child2 = generateNotificationRecord(
1417 mTestNotificationChannel, 3, "group", false);
1418 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1419 final NotificationRecord newGroup = generateNotificationRecord(
1420 mTestNotificationChannel, 4, "group2", false);
1421 mService.addNotification(parent);
1422 mService.addNotification(child);
1423 mService.addNotification(child2);
1424 mService.addNotification(newGroup);
1425 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1426 child2.sbn.getKey(), newGroup.sbn.getKey()};
1427 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1428 waitForIdle();
1429 StatusBarNotification[] notifs =
1430 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1431 assertEquals(0, notifs.length);
1432 }
1433
1434 @Test
1435 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1436 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1437 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001438 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001439 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1440 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1441 waitForIdle();
1442 StatusBarNotification[] notifs =
1443 mBinderService.getActiveNotifications(sbn.getPackageName());
1444 assertEquals(0, notifs.length);
1445 }
1446
1447 @Test
1448 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1449 final NotificationRecord notif = generateNotificationRecord(
1450 mTestNotificationChannel, 1, "group", true);
1451 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1452 mService.addNotification(notif);
1453 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1454 notif.getUserId(), 0, null);
1455 waitForIdle();
1456 StatusBarNotification[] notifs =
1457 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1458 assertEquals(0, notifs.length);
1459 }
1460
1461 @Test
1462 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1463 final NotificationRecord notif = generateNotificationRecord(
1464 mTestNotificationChannel, 1, "group", true);
1465 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1466 mService.addNotification(notif);
1467
1468 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1469 notif.getUserId());
1470 waitForIdle();
1471 StatusBarNotification[] notifs =
1472 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1473 assertEquals(1, notifs.length);
1474 }
1475
1476 @Test
1477 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1478 final NotificationRecord parent = generateNotificationRecord(
1479 mTestNotificationChannel, 1, "group", true);
1480 final NotificationRecord child = generateNotificationRecord(
1481 mTestNotificationChannel, 2, "group", false);
1482 final NotificationRecord child2 = generateNotificationRecord(
1483 mTestNotificationChannel, 3, "group", false);
1484 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1485 final NotificationRecord newGroup = generateNotificationRecord(
1486 mTestNotificationChannel, 4, "group2", false);
1487 mService.addNotification(parent);
1488 mService.addNotification(child);
1489 mService.addNotification(child2);
1490 mService.addNotification(newGroup);
1491 mService.getBinderService().cancelNotificationsFromListener(null, null);
1492 waitForIdle();
1493 StatusBarNotification[] notifs =
1494 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1495 assertEquals(1, notifs.length);
1496 }
1497
1498 @Test
1499 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1500 throws Exception {
1501 final NotificationRecord parent = generateNotificationRecord(
1502 mTestNotificationChannel, 1, "group", true);
1503 final NotificationRecord child = generateNotificationRecord(
1504 mTestNotificationChannel, 2, "group", false);
1505 final NotificationRecord child2 = generateNotificationRecord(
1506 mTestNotificationChannel, 3, "group", false);
1507 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1508 final NotificationRecord newGroup = generateNotificationRecord(
1509 mTestNotificationChannel, 4, "group2", false);
1510 mService.addNotification(parent);
1511 mService.addNotification(child);
1512 mService.addNotification(child2);
1513 mService.addNotification(newGroup);
1514 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1515 child2.sbn.getKey(), newGroup.sbn.getKey()};
1516 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1517 waitForIdle();
1518 StatusBarNotification[] notifs =
1519 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1520 assertEquals(0, notifs.length);
1521 }
1522
1523 @Test
1524 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1525 final NotificationRecord parent = generateNotificationRecord(
1526 mTestNotificationChannel, 1, "group", true);
1527 final NotificationRecord child = generateNotificationRecord(
1528 mTestNotificationChannel, 2, "group", false);
1529 final NotificationRecord child2 = generateNotificationRecord(
1530 mTestNotificationChannel, 3, "group", false);
1531 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1532 final NotificationRecord newGroup = generateNotificationRecord(
1533 mTestNotificationChannel, 4, "group2", false);
1534 mService.addNotification(parent);
1535 mService.addNotification(child);
1536 mService.addNotification(child2);
1537 mService.addNotification(newGroup);
1538 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1539 parent.getUserId());
1540 waitForIdle();
1541 StatusBarNotification[] notifs =
1542 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1543 assertEquals(1, notifs.length);
1544 }
1545
1546 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001547 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001548 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001549 mService.setPreferencesHelper(mPreferencesHelper);
1550 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001551 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001552 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001553
Julia Reynoldsbad42972017-04-25 13:52:49 -04001554 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001555 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001556 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001557 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001558 anyString(), anyInt(), eq("foo"), anyBoolean());
1559 }
1560
1561 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001562 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001563 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001564 mService.setPreferencesHelper(mPreferencesHelper);
1565 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001566 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001567 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001568
Julia Reynoldsbad42972017-04-25 13:52:49 -04001569 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001570 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001571 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001572 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001573 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001574 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001575
1576 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001577 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001578 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001579
Julia Reynolds4f5020d2019-06-03 12:48:49 -04001580 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001581 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1582 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1583
1584 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1585 captor.getValue().getAction());
1586 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynolds4f5020d2019-06-03 12:48:49 -04001587 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1588 }
1589
1590 @Test
1591 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1592 mService.setPreferencesHelper(mPreferencesHelper);
1593
1594 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1595 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001596 }
1597
1598 @Test
1599 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001600 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001601
1602 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1603 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1604 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1605
1606 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1607 captor.getValue().getAction());
1608 assertEquals(PKG, captor.getValue().getPackage());
1609 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1610 }
1611
1612 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001613 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001614 mService.setPreferencesHelper(mPreferencesHelper);
1615 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001616 eq(mTestNotificationChannel.getId()), anyBoolean()))
1617 .thenReturn(mTestNotificationChannel);
1618
1619 NotificationChannel updatedChannel =
1620 new NotificationChannel(mTestNotificationChannel.getId(),
1621 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1622
1623 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1624 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1625 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1626
1627 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1628 captor.getValue().getAction());
1629 assertEquals(PKG, captor.getValue().getPackage());
1630 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001631 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001632 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1633 }
1634
1635 @Test
1636 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1637 NotificationChannel existingChannel =
1638 new NotificationChannel(mTestNotificationChannel.getId(),
1639 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001640 mService.setPreferencesHelper(mPreferencesHelper);
1641 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001642 eq(mTestNotificationChannel.getId()), anyBoolean()))
1643 .thenReturn(existingChannel);
1644
1645 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1646 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1647 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1648
1649 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1650 captor.getValue().getAction());
1651 assertEquals(PKG, captor.getValue().getPackage());
1652 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001653 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001654 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1655 }
1656
1657 @Test
1658 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1659 NotificationChannel existingChannel =
1660 new NotificationChannel(mTestNotificationChannel.getId(),
1661 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001662 mService.setPreferencesHelper(mPreferencesHelper);
1663 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001664 eq(mTestNotificationChannel.getId()), anyBoolean()))
1665 .thenReturn(existingChannel);
1666
1667 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1668 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1669 }
1670
1671 @Test
1672 public void testUpdateGroupNotifyCreatorBlock() 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 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1679 updated.setBlocked(true);
1680
1681 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1682 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1683 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1684
1685 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1686 captor.getValue().getAction());
1687 assertEquals(PKG, captor.getValue().getPackage());
1688 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001689 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001690 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1691 }
1692
1693 @Test
1694 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1695 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1696 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001697 mService.setPreferencesHelper(mPreferencesHelper);
1698 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001699 .thenReturn(existing);
1700
1701 mBinderService.updateNotificationChannelGroupForPackage(
1702 PKG, 0, new NotificationChannelGroup("id", "name"));
1703 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1704 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1705
1706 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1707 captor.getValue().getAction());
1708 assertEquals(PKG, captor.getValue().getPackage());
1709 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001710 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001711 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1712 }
1713
1714 @Test
1715 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1716 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001717 mService.setPreferencesHelper(mPreferencesHelper);
1718 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001719 .thenReturn(existing);
1720
1721 mBinderService.updateNotificationChannelGroupForPackage(
1722 PKG, 0, new NotificationChannelGroup("id", "new name"));
1723 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1724 }
1725
1726 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001727 public void testCreateChannelNotifyListener() throws Exception {
1728 List<String> associations = new ArrayList<>();
1729 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001730 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001731 mService.setPreferencesHelper(mPreferencesHelper);
1732 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001733 eq(mTestNotificationChannel.getId()), anyBoolean()))
1734 .thenReturn(mTestNotificationChannel);
1735 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001736 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001737 eq(channel2.getId()), anyBoolean()))
1738 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001739 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1740 eq(channel2), anyBoolean(), anyBoolean()))
1741 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001742
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001743 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001744 mBinderService.createNotificationChannels(PKG,
1745 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001746 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001747 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001748 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001749 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001750 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001751 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1752 }
1753
1754 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001755 public void testCreateChannelGroupNotifyListener() throws Exception {
1756 List<String> associations = new ArrayList<>();
1757 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001758 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001759 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001760 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1761 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1762
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001763 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001764 mBinderService.createNotificationChannelGroups(PKG,
1765 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001766 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001767 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001768 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001769 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001770 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001771 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1772 }
1773
1774 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001775 public void testUpdateChannelNotifyListener() throws Exception {
1776 List<String> associations = new ArrayList<>();
1777 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001778 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001779 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001780 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001781 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001782 eq(mTestNotificationChannel.getId()), anyBoolean()))
1783 .thenReturn(mTestNotificationChannel);
1784
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001785 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001786 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001787 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001788 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001789 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1790 }
1791
1792 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001793 public void testDeleteChannelNotifyListener() throws Exception {
1794 List<String> associations = new ArrayList<>();
1795 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001796 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001797 mService.setPreferencesHelper(mPreferencesHelper);
1798 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001799 eq(mTestNotificationChannel.getId()), anyBoolean()))
1800 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001801 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001802 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001803 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001804 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001805 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1806 }
1807
1808 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001809 public void testDeleteChannelGroupNotifyListener() throws Exception {
1810 List<String> associations = new ArrayList<>();
1811 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001812 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001813 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001814 mService.setPreferencesHelper(mPreferencesHelper);
1815 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001816 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001817 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001818 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001819 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001820 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001821 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1822 }
1823
1824 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001825 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001826 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -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);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001830 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001831 eq(mTestNotificationChannel.getId()), anyBoolean()))
1832 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001833
1834 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001835 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001836
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001837 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001838 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001839
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001840 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001841 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001842 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1843 }
1844
1845 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001846 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001847 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001848 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001849 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001850
1851 try {
1852 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001853 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001854 fail("listeners that don't have a companion device shouldn't be able to call this");
1855 } catch (SecurityException e) {
1856 // pass
1857 }
1858
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001859 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001860 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001861
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001862 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001863 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1864 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1865 }
1866
1867 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001868 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001869 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001870 List<String> associations = new ArrayList<>();
1871 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001872 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001873 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04001874 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001875 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001876 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001877
1878 try {
1879 mBinderService.updateNotificationChannelFromPrivilegedListener(
1880 null, PKG, UserHandle.ALL, mTestNotificationChannel);
1881 fail("incorrectly allowed a change to a user listener cannot see");
1882 } catch (SecurityException e) {
1883 // pass
1884 }
1885
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001886 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001887 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001888
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001889 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001890 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001891 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1892 }
1893
1894 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001895 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001896 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001897 List<String> associations = new ArrayList<>();
1898 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001899 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001900
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001901 mBinderService.getNotificationChannelsFromPrivilegedListener(
1902 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001903
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001904 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001905 anyString(), anyInt(), anyBoolean());
1906 }
1907
1908 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001909 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001910 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001911 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001912 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001913
1914 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001915 mBinderService.getNotificationChannelsFromPrivilegedListener(
1916 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001917 fail("listeners that don't have a companion device shouldn't be able to call this");
1918 } catch (SecurityException e) {
1919 // pass
1920 }
1921
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001922 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001923 anyString(), anyInt(), anyBoolean());
1924 }
1925
1926 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001927 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
1928 throws Exception {
1929 mService.setPreferencesHelper(mPreferencesHelper);
1930 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1931 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
1932
1933 mBinderService.getNotificationChannelsFromPrivilegedListener(
1934 null, PKG, Process.myUserHandle());
1935
1936 verify(mPreferencesHelper, times(1)).getNotificationChannels(
1937 anyString(), anyInt(), anyBoolean());
1938 }
1939
1940 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04001941 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
1942 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001943 mService.setPreferencesHelper(mPreferencesHelper);
1944 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1945 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
1946
1947 try {
1948 mBinderService.getNotificationChannelsFromPrivilegedListener(
1949 null, PKG, Process.myUserHandle());
1950 fail("listeners that don't have a companion device shouldn't be able to call this");
1951 } catch (SecurityException e) {
1952 // pass
1953 }
1954
1955 verify(mPreferencesHelper, never()).getNotificationChannels(
1956 anyString(), anyInt(), anyBoolean());
1957 }
1958
1959 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001960 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001961 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001962 List<String> associations = new ArrayList<>();
1963 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001964 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001965 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1966 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001967 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001968
1969 try {
1970 mBinderService.getNotificationChannelsFromPrivilegedListener(
1971 null, PKG, Process.myUserHandle());
1972 fail("listener getting channels from a user they cannot see");
1973 } catch (SecurityException e) {
1974 // pass
1975 }
1976
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001977 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001978 anyString(), anyInt(), anyBoolean());
1979 }
1980
1981 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001982 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001983 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001984 List<String> associations = new ArrayList<>();
1985 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001986 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001987
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001988 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1989 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001990
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001991 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001992 }
1993
1994 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001995 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001996 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001997 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001998 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001999
2000 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002001 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2002 null, PKG, Process.myUserHandle());
2003 fail("listeners that don't have a companion device shouldn't be able to call this");
2004 } catch (SecurityException e) {
2005 // pass
2006 }
2007
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002008 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002009 }
2010
2011 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002012 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002013 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002014 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002015 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002016 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2017 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002018 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002019 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002020 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2021 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002022 fail("listeners that don't have a companion device shouldn't be able to call this");
2023 } catch (SecurityException e) {
2024 // pass
2025 }
2026
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002027 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002028 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002029
2030 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002031 public void testHasCompanionDevice_failure() throws Exception {
2032 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2033 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002034 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002035 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002036
2037 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002038 public void testHasCompanionDevice_noService() {
2039 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04002040
Julia Reynolds503ed942017-10-04 16:04:56 -04002041 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002042 }
2043
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002044 @Test
2045 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2046 final NotificationRecord nonGrouped = generateNotificationRecord(
2047 mTestNotificationChannel, 1, null, false);
2048 final NotificationRecord grouped = generateNotificationRecord(
2049 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002050 mService.addNotification(grouped);
2051 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002052
2053 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002054 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002055 nonGrouped.getKey(), 100, null);
2056 snoozeNotificationRunnable.run();
2057
2058 // only snooze the one notification
2059 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002060 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002061 }
2062
2063 @Test
2064 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2065 final NotificationRecord parent = generateNotificationRecord(
2066 mTestNotificationChannel, 1, "group", true);
2067 final NotificationRecord child = generateNotificationRecord(
2068 mTestNotificationChannel, 2, "group", false);
2069 final NotificationRecord child2 = generateNotificationRecord(
2070 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002071 mService.addNotification(parent);
2072 mService.addNotification(child);
2073 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002074
2075 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002076 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002077 parent.getKey(), 100, null);
2078 snoozeNotificationRunnable.run();
2079
2080 // snooze parent and children
2081 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2082 }
2083
2084 @Test
2085 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2086 final NotificationRecord parent = generateNotificationRecord(
2087 mTestNotificationChannel, 1, "group", true);
2088 final NotificationRecord child = generateNotificationRecord(
2089 mTestNotificationChannel, 2, "group", false);
2090 final NotificationRecord child2 = generateNotificationRecord(
2091 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002092 mService.addNotification(parent);
2093 mService.addNotification(child);
2094 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002095
2096 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002097 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002098 child2.getKey(), 100, null);
2099 snoozeNotificationRunnable.run();
2100
2101 // only snooze the one child
2102 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2103 }
2104
2105 @Test
2106 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2107 final NotificationRecord parent = generateNotificationRecord(
2108 mTestNotificationChannel, 1, "group", true);
2109 assertTrue(parent.sbn.getNotification().isGroupSummary());
2110 final NotificationRecord child = generateNotificationRecord(
2111 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002112 mService.addNotification(parent);
2113 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002114
2115 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002116 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002117 child.getKey(), 100, null);
2118 snoozeNotificationRunnable.run();
2119
2120 // snooze child and summary
2121 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2122 }
2123
2124 @Test
2125 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2126 final NotificationRecord child = generateNotificationRecord(
2127 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002128 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002129
2130 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002131 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002132 child.getKey(), 100, null);
2133 snoozeNotificationRunnable.run();
2134
2135 // snooze child only
2136 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2137 }
2138
2139 @Test
2140 public void testPostGroupChild_unsnoozeParent() throws Exception {
2141 final NotificationRecord child = generateNotificationRecord(
2142 mTestNotificationChannel, 2, "group", false);
2143
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002144 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002145 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2146 waitForIdle();
2147
2148 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2149 anyString(), anyInt(), eq(child.getGroupKey()));
2150 }
2151
2152 @Test
2153 public void testPostNonGroup_noUnsnoozing() throws Exception {
2154 final NotificationRecord record = generateNotificationRecord(
2155 mTestNotificationChannel, 2, null, false);
2156
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002157 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002158 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2159 waitForIdle();
2160
2161 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2162 }
2163
2164 @Test
2165 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2166 final NotificationRecord parent = generateNotificationRecord(
2167 mTestNotificationChannel, 2, "group", true);
2168
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002169 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002170 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2171 waitForIdle();
2172
2173 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2174 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002175
2176 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002177 public void testSetListenerAccessForUser() throws Exception {
2178 UserHandle user = UserHandle.of(10);
2179 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002180 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2181
Julia Reynolds92febc32017-10-26 11:30:31 -04002182
2183 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2184 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2185 c.flattenToString(), user.getIdentifier(), true, true);
2186 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2187 c.flattenToString(), user.getIdentifier(), false, true);
2188 verify(mAssistants, never()).setPackageOrComponentEnabled(
2189 any(), anyInt(), anyBoolean(), anyBoolean());
2190 }
2191
2192 @Test
2193 public void testSetAssistantAccessForUser() throws Exception {
2194 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002195 List<UserInfo> uis = new ArrayList<>();
2196 UserInfo ui = new UserInfo();
2197 ui.id = 10;
2198 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002199 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002200 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2201
2202 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002203
2204 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2205 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2206 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002207 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002208 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2209 c.flattenToString(), user.getIdentifier(), false, true);
2210 verify(mListeners, never()).setPackageOrComponentEnabled(
2211 any(), anyInt(), anyBoolean(), anyBoolean());
2212 }
2213
2214 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002215 public void testGetAssistantAllowedForUser() throws Exception {
2216 UserHandle user = UserHandle.of(10);
2217 try {
2218 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2219 } catch (IllegalStateException e) {
2220 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2221 throw e;
2222 }
2223 }
2224 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2225 }
2226
2227 @Test
2228 public void testGetAssistantAllowed() throws Exception {
2229 try {
2230 mBinderService.getAllowedNotificationAssistant();
2231 } catch (IllegalStateException e) {
2232 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2233 throw e;
2234 }
2235 }
2236 verify(mAssistants, times(1)).getAllowedComponents(0);
2237 }
2238
2239 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002240 public void testSetDndAccessForUser() throws Exception {
2241 UserHandle user = UserHandle.of(10);
2242 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002243 mBinderService.setNotificationPolicyAccessGrantedForUser(
2244 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002245
2246 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2247 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2248 c.getPackageName(), user.getIdentifier(), true, true);
2249 verify(mAssistants, never()).setPackageOrComponentEnabled(
2250 any(), anyInt(), anyBoolean(), anyBoolean());
2251 verify(mListeners, never()).setPackageOrComponentEnabled(
2252 any(), anyInt(), anyBoolean(), anyBoolean());
2253 }
2254
2255 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002256 public void testSetListenerAccess() throws Exception {
2257 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002258 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002259
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002260 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002261 c.flattenToString(), 0, true, true);
2262 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2263 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002264 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002265 any(), anyInt(), anyBoolean(), anyBoolean());
2266 }
2267
2268 @Test
2269 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002270 List<UserInfo> uis = new ArrayList<>();
2271 UserInfo ui = new UserInfo();
2272 ui.id = 0;
2273 uis.add(ui);
2274 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002275 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002276
2277 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002278
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002279 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002280 c.flattenToString(), 0, true, true);
2281 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2282 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002283 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002284 any(), anyInt(), anyBoolean(), anyBoolean());
2285 }
2286
2287 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002288 public void testSetAssistantAccess_multiProfile() throws Exception {
2289 List<UserInfo> uis = new ArrayList<>();
2290 UserInfo ui = new UserInfo();
2291 ui.id = 0;
2292 uis.add(ui);
2293 UserInfo ui10 = new UserInfo();
2294 ui10.id = 10;
2295 uis.add(ui10);
2296 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2297 ComponentName c = ComponentName.unflattenFromString("package/Component");
2298
2299 mBinderService.setNotificationAssistantAccessGranted(c, true);
2300
2301 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2302 c.flattenToString(), 0, true, true);
2303 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2304 c.flattenToString(), 10, true, true);
2305 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2306 c.flattenToString(), 0, false, true);
2307 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2308 c.flattenToString(), 10, false, true);
2309 verify(mListeners, never()).setPackageOrComponentEnabled(
2310 any(), anyInt(), anyBoolean(), anyBoolean());
2311 }
2312
2313 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002314 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2315 ArrayList<ComponentName> componentList = new ArrayList<>();
2316 ComponentName c = ComponentName.unflattenFromString("package/Component");
2317 componentList.add(c);
2318 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002319 List<UserInfo> uis = new ArrayList<>();
2320 UserInfo ui = new UserInfo();
2321 ui.id = 0;
2322 uis.add(ui);
2323 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002324
Julia Reynolds4afe2642019-05-01 08:42:24 -04002325 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002326
2327 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2328 c.flattenToString(), 0, true, false);
2329 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2330 c.flattenToString(), 0, false, false);
2331 verify(mListeners, never()).setPackageOrComponentEnabled(
2332 any(), anyInt(), anyBoolean(), anyBoolean());
2333 }
2334
2335 @Test
2336 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002337 List<UserInfo> uis = new ArrayList<>();
2338 UserInfo ui = new UserInfo();
2339 ui.id = 10;
2340 uis.add(ui);
2341 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002342 ArrayList<ComponentName> componentList = new ArrayList<>();
2343 ComponentName c = ComponentName.unflattenFromString("package/Component");
2344 componentList.add(c);
2345 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002346 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002347
Julia Reynolds4afe2642019-05-01 08:42:24 -04002348 mBinderService.setNotificationAssistantAccessGrantedForUser(
2349 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002350
2351 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2352 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002353 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002354 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2355 c.flattenToString(), user.getIdentifier(), false, false);
2356 verify(mListeners, never()).setPackageOrComponentEnabled(
2357 any(), anyInt(), anyBoolean(), anyBoolean());
2358 }
2359
2360 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002361 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2362 throws Exception {
2363 List<UserInfo> uis = new ArrayList<>();
2364 UserInfo ui = new UserInfo();
2365 ui.id = 0;
2366 uis.add(ui);
2367 UserInfo ui10 = new UserInfo();
2368 ui10.id = 10;
2369 uis.add(ui10);
2370 UserHandle user = ui.getUserHandle();
2371 ArrayList<ComponentName> componentList = new ArrayList<>();
2372 ComponentName c = ComponentName.unflattenFromString("package/Component");
2373 componentList.add(c);
2374 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2375 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2376
2377 mBinderService.setNotificationAssistantAccessGrantedForUser(
2378 null, user.getIdentifier(), true);
2379
2380 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2381 c.flattenToString(), user.getIdentifier(), true, false);
2382 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2383 c.flattenToString(), ui10.id, true, false);
2384 verify(mAssistants).setUserSet(0, true);
2385 verify(mAssistants).setUserSet(10, true);
2386 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2387 c.flattenToString(), user.getIdentifier(), false, false);
2388 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2389 c.flattenToString(), ui10.id, false, false);
2390 verify(mListeners, never()).setPackageOrComponentEnabled(
2391 any(), anyInt(), anyBoolean(), anyBoolean());
2392 }
2393
2394 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002395 public void testSetDndAccess() throws Exception {
2396 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002397
2398 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002399
2400 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2401 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002402 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002403 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002404 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002405 any(), anyInt(), anyBoolean(), anyBoolean());
2406 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002407
2408 @Test
2409 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2410 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2411 ComponentName c = ComponentName.unflattenFromString("package/Component");
2412 mBinderService.setNotificationListenerAccessGranted(c, true);
2413
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002414 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002415 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002416 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002417 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002418 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002419 any(), anyInt(), anyBoolean(), anyBoolean());
2420 }
2421
2422 @Test
2423 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2424 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2425 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002426 List<UserInfo> uis = new ArrayList<>();
2427 UserInfo ui = new UserInfo();
2428 ui.id = 0;
2429 uis.add(ui);
2430 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2431
Julia Reynolds68263d12017-06-21 14:21:19 -04002432 mBinderService.setNotificationAssistantAccessGranted(c, true);
2433
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002434 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002435 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002436 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002437 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002438 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002439 any(), anyInt(), anyBoolean(), anyBoolean());
2440 }
2441
2442 @Test
2443 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2444 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2445 ComponentName c = ComponentName.unflattenFromString("package/Component");
2446 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2447
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002448 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002449 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002450 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002451 anyString(), anyInt(), anyBoolean(), anyBoolean());
2452 verify(mAssistants, never()).setPackageOrComponentEnabled(
2453 any(), anyInt(), anyBoolean(), anyBoolean());
2454 }
2455
2456 @Test
2457 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2458 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2459 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2460 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002461
2462 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002463
2464 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2465 c.flattenToString(), 0, true, true);
2466 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002467 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002468 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002469 any(), anyInt(), anyBoolean(), anyBoolean());
2470 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002471
2472 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002473 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2474 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2475 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2476 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002477 List<UserInfo> uis = new ArrayList<>();
2478 UserInfo ui = new UserInfo();
2479 ui.id = 0;
2480 uis.add(ui);
2481 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2482
2483 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002484
2485 verify(mListeners, never()).setPackageOrComponentEnabled(
2486 anyString(), anyInt(), anyBoolean(), anyBoolean());
2487 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2488 c.flattenToString(), 0, false, true);
2489 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2490 c.flattenToString(), 0, true, true);
2491 }
2492
2493 @Test
2494 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2495 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2496 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2497 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002498
2499 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002500
2501 verify(mListeners, never()).setPackageOrComponentEnabled(
2502 anyString(), anyInt(), anyBoolean(), anyBoolean());
2503 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2504 c.getPackageName(), 0, true, true);
2505 verify(mAssistants, never()).setPackageOrComponentEnabled(
2506 any(), anyInt(), anyBoolean(), anyBoolean());
2507 }
2508
2509 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002510 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2511 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002512 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002513 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002514 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002515 runnable.run();
2516 waitForIdle();
2517
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002518 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002519 }
2520
2521 @Test
2522 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2523 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002524 NotificationRecord r =
2525 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002526 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002527
2528 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002529 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002530 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002531 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002532 runnable.run();
2533 waitForIdle();
2534
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002535 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002536 }
2537
2538 @Test
2539 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2540 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002541 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2542 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002543 mService.addNotification(r);
2544 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002545
2546 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002547 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002548 runnable.run();
2549 waitForIdle();
2550
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002551 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002552 }
Beverly40239d92017-07-07 10:20:41 -04002553
Julia Reynolds4db59552017-06-30 13:34:01 -04002554 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002555 public void testDontAutogroupIfCritical() throws Exception {
2556 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2557 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2558 mService.addEnqueuedNotification(r);
2559 NotificationManagerService.PostNotificationRunnable runnable =
2560 mService.new PostNotificationRunnable(r.getKey());
2561 runnable.run();
2562
2563 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2564 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2565 runnable = mService.new PostNotificationRunnable(r.getKey());
2566 mService.addEnqueuedNotification(r);
2567
2568 runnable.run();
2569 waitForIdle();
2570
2571 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2572 }
2573
2574 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002575 public void testNoFakeColorizedPermission() throws Exception {
2576 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2577 Notification.Builder nb = new Notification.Builder(mContext,
2578 mTestNotificationChannel.getId())
2579 .setContentTitle("foo")
2580 .setColorized(true)
2581 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2582 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002583 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
2584 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002585 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2586
2587 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2588 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2589 waitForIdle();
2590
Julia Reynolds503ed942017-10-04 16:04:56 -04002591 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds4db59552017-06-30 13:34:01 -04002592 PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
2593
2594 assertFalse(posted.getNotification().isColorized());
2595 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002596
2597 @Test
2598 public void testGetNotificationCountLocked() throws Exception {
2599 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002600 NotificationRecord r =
2601 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002602 mService.addEnqueuedNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002603 }
2604 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002605 NotificationRecord r =
2606 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002607 mService.addNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002608 }
2609
2610 // another package
2611 Notification n =
2612 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2613 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2614 .build();
2615
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002616 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2617 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002618 NotificationRecord otherPackage =
2619 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002620 mService.addEnqueuedNotification(otherPackage);
2621 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002622
2623 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002624 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002625 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002626 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002627 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002628 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002629 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002630 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002631
2632 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002633 assertEquals(39,
Julia Reynolds503ed942017-10-04 16:04:56 -04002634 mService.getNotificationCountLocked(PKG, userId, 0, "tag"));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002635 }
2636
2637 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002638 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002639 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002640 mService.setRankingHandler(rh);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002641
2642 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002643 mService.addNotification(r);
2644 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002645
2646 verify(rh, times(1)).requestSort();
2647 }
2648
2649 @Test
2650 public void testRemoveAutogroup_requestsSort() throws Exception {
2651 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002652 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002653
2654 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2655 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002656 mService.addNotification(r);
2657 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002658
Julia Reynolds51710712017-07-19 13:48:07 -04002659 verify(rh, times(1)).requestSort();
2660 }
2661
2662 @Test
2663 public void testReaddAutogroup_noSort() throws Exception {
2664 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002665 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002666
2667 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2668 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002669 mService.addNotification(r);
2670 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002671
2672 verify(rh, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002673 }
2674
2675 @Test
2676 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002677 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002678 NotificationManagerService.WorkerHandler handler = mock(
2679 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002680 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002681
2682 Map<String, Answer> answers = getSignalExtractorSideEffects();
2683 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002684 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002685 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002686 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002687
2688 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2689
Julia Reynolds503ed942017-10-04 16:04:56 -04002690 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002691 }
2692 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2693 }
2694
2695 @Test
2696 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002697 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002698 NotificationManagerService.WorkerHandler handler = mock(
2699 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002700 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002701
2702 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002703 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002704
Julia Reynolds503ed942017-10-04 16:04:56 -04002705 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002706 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002707 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002708
2709 @Test
2710 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002711 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002712 + "<ranking></ranking>"
2713 + "<enabled_listeners>"
2714 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2715 + "</enabled_listeners>"
2716 + "<enabled_assistants>"
2717 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2718 + "</enabled_assistants>"
2719 + "<dnd_apps>"
2720 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2721 + "</dnd_apps>"
2722 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002723 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002724 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2725 false,
2726 UserHandle.USER_ALL);
2727 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2728 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2729 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002730
2731 // numbers are inflated for setup
2732 verify(mListeners, times(1)).migrateToXml();
2733 verify(mConditionProviders, times(1)).migrateToXml();
2734 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002735 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002736 }
2737
2738 @Test
2739 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2740 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002741 + "<ranking></ranking>"
2742 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002743 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002744 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2745 false,
2746 UserHandle.USER_ALL);
2747 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2748 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2749 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002750
2751 // numbers are inflated for setup
2752 verify(mListeners, times(2)).migrateToXml();
2753 verify(mConditionProviders, times(2)).migrateToXml();
2754 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002755 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002756 }
2757
Annie Meng8b646fd2019-02-01 18:46:42 +00002758 @Test
2759 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2760 final String policyXml = "<notification-policy version=\"1\">"
2761 + "<ranking></ranking>"
2762 + "<enabled_listeners>"
2763 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2764 + "</enabled_listeners>"
2765 + "<enabled_assistants>"
2766 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2767 + "</enabled_assistants>"
2768 + "<dnd_apps>"
2769 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2770 + "</dnd_apps>"
2771 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002772 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00002773 mService.readPolicyXml(
2774 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2775 true,
2776 10);
2777 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2778 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2779 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2780 }
2781
2782 @Test
2783 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2784 final String policyXml = "<notification-policy version=\"1\">"
2785 + "<ranking></ranking>"
2786 + "<enabled_listeners>"
2787 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2788 + "</enabled_listeners>"
2789 + "<enabled_assistants>"
2790 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2791 + "</enabled_assistants>"
2792 + "<dnd_apps>"
2793 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2794 + "</dnd_apps>"
2795 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002796 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00002797 mService.readPolicyXml(
2798 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2799 true,
2800 10);
2801 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
2802 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
2803 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
2804 }
Beverlyd4f96492017-08-02 13:36:11 -04002805
2806 @Test
2807 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
2808 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002809 mService.mZenModeHelper = mZenModeHelper;
2810 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04002811 new Intent(Intent.ACTION_LOCALE_CHANGED));
2812
2813 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
2814 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002815
2816 @Test
2817 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06002818 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002819 final ApplicationInfo legacy = new ApplicationInfo();
2820 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
2821 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
2822 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002823 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
2824 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002825 getContext().setMockPackageManager(mPackageManagerClient);
2826
2827 Notification.Builder nb = new Notification.Builder(mContext,
2828 NotificationChannel.DEFAULT_CHANNEL_ID)
2829 .setContentTitle("foo")
2830 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002831 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002832 .setPriority(Notification.PRIORITY_MIN);
2833
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002834 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
2835 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002836
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002837 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
2838 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002839 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002840
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002841 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002842 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002843
2844 nb = new Notification.Builder(mContext)
2845 .setContentTitle("foo")
2846 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002847 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002848 .setPriority(Notification.PRIORITY_MIN);
2849
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002850 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
2851 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002852
2853 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
2854 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2855 waitForIdle();
2856 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002857 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002858
2859 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04002860 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002861 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
2862 }
Julia Reynolds503ed942017-10-04 16:04:56 -04002863
2864 @Test
2865 public void testStats_updatedOnDirectReply() throws Exception {
2866 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2867 mService.addNotification(r);
2868
2869 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
2870 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00002871 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04002872 }
2873
2874 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002875 public void testStats_updatedOnUserExpansion() throws Exception {
2876 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002877 mService.addNotification(r);
2878
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002879 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
2880 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002881 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002882 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002883
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002884 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
2885 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002886 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002887 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2888 }
2889
2890 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002891 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
2892 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2893 mService.addNotification(r);
2894
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002895 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
2896 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002897 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002898 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
2899
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002900 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
2901 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002902 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002903 verify(mAssistants).notifyAssistantExpansionChangedLocked(
2904 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002905 }
2906
2907 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04002908 public void testStats_updatedOnViewSettings() throws Exception {
2909 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2910 mService.addNotification(r);
2911
2912 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
2913 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
2914 }
2915
2916 @Test
2917 public void testStats_updatedOnVisibilityChanged() throws Exception {
2918 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2919 mService.addNotification(r);
2920
Dieter Hsud39f0d52018-04-14 02:08:30 +08002921 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002922 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2923 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
2924 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2925 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2926 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
2927 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2928 }
2929
2930 @Test
2931 public void testStats_dismissalSurface() throws Exception {
2932 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2933 mService.addNotification(r);
2934
Dieter Hsud39f0d52018-04-14 02:08:30 +08002935 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002936 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002937 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2938 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04002939 waitForIdle();
2940
2941 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
2942 }
2943
2944 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002945 public void testStats_dismissalSentiment() throws Exception {
2946 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2947 mService.addNotification(r);
2948
2949 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2950 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2951 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2952 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
2953 waitForIdle();
2954
2955 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
2956 r.getStats().getDismissalSentiment());
2957 }
2958
2959 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002960 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002961 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2962 mService.addNotification(r);
2963 NotificationManagerService.WorkerHandler handler = mock(
2964 NotificationManagerService.WorkerHandler.class);
2965 mService.setHandler(handler);
2966
Julia Reynolds70aaea72018-07-13 13:38:34 -04002967 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2968
Julia Reynolds503ed942017-10-04 16:04:56 -04002969 Bundle signals = new Bundle();
2970 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04002971 USER_SENTIMENT_NEGATIVE);
2972 Adjustment adjustment = new Adjustment(
2973 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2974 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2975
2976 waitForIdle();
2977
2978 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2979 }
2980
2981 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05002982 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002983 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2984 mService.addNotification(r);
2985 NotificationManagerService.WorkerHandler handler = mock(
2986 NotificationManagerService.WorkerHandler.class);
2987 mService.setHandler(handler);
2988
2989 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04002990 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002991 Adjustment adjustment = new Adjustment(
2992 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2993 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
2994 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2995
2996 waitForIdle();
2997
2998 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2999 verify(handler, times(1)).scheduleCancelNotification(any());
3000 }
3001
3002 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003003 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3004 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3005 mService.addEnqueuedNotification(r);
3006 NotificationManagerService.WorkerHandler handler = mock(
3007 NotificationManagerService.WorkerHandler.class);
3008 mService.setHandler(handler);
3009 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3010
3011 Bundle signals = new Bundle();
3012 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3013 USER_SENTIMENT_NEGATIVE);
3014 Adjustment adjustment = new Adjustment(
3015 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3016 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3017
3018 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3019 }
3020
3021 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003022 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003023 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3024 mService.addEnqueuedNotification(r);
3025 NotificationManagerService.WorkerHandler handler = mock(
3026 NotificationManagerService.WorkerHandler.class);
3027 mService.setHandler(handler);
3028 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3029
3030 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003031 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003032 Adjustment adjustment = new Adjustment(
3033 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3034 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3035
3036 assertEquals(IMPORTANCE_LOW, r.getImportance());
3037 }
3038
3039 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003040 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3041 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3042 mService.addEnqueuedNotification(r);
3043 NotificationManagerService.WorkerHandler handler = mock(
3044 NotificationManagerService.WorkerHandler.class);
3045 mService.setHandler(handler);
3046 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3047
3048 Bundle signals = new Bundle();
3049 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3050 USER_SENTIMENT_NEGATIVE);
3051 Adjustment adjustment = new Adjustment(
3052 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3053 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3054
3055 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3056
3057 waitForIdle();
3058
3059 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3060 }
3061
3062 @Test
3063 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3064 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3065 mService.addNotification(r);
3066 NotificationManagerService.WorkerHandler handler = mock(
3067 NotificationManagerService.WorkerHandler.class);
3068 mService.setHandler(handler);
3069 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3070
3071 Bundle signals = new Bundle();
3072 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3073 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003074 Adjustment adjustment = new Adjustment(
3075 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3076 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3077
3078 waitForIdle();
3079
3080 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3081 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003082
3083 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003084 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3085 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3086 mService.addNotification(r);
3087 NotificationManagerService.WorkerHandler handler = mock(
3088 NotificationManagerService.WorkerHandler.class);
3089 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003090 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003091
3092 Bundle signals = new Bundle();
3093 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003094 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003095 Adjustment adjustment = new Adjustment(
3096 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3097 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3098
3099 waitForIdle();
3100
3101 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3102 }
3103
3104 @Test
3105 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3106 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3107 mService.addEnqueuedNotification(r);
3108 NotificationManagerService.WorkerHandler handler = mock(
3109 NotificationManagerService.WorkerHandler.class);
3110 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003111 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003112
3113 Bundle signals = new Bundle();
3114 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003115 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003116 Adjustment adjustment = new Adjustment(
3117 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3118 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3119
Julia Reynolds70aaea72018-07-13 13:38:34 -04003120 assertEquals(USER_SENTIMENT_NEGATIVE,
Julia Reynolds666ccf02018-06-18 10:19:20 -04003121 r.getUserSentiment());
3122 }
3123
3124 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003125 public void testRestore() throws Exception {
3126 int systemChecks = mService.countSystemChecks;
3127 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
3128 assertEquals(1, mService.countSystemChecks - systemChecks);
3129 }
3130
3131 @Test
3132 public void testBackup() throws Exception {
3133 int systemChecks = mService.countSystemChecks;
3134 mBinderService.getBackupPayload(1);
3135 assertEquals(1, mService.countSystemChecks - systemChecks);
3136 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003137
3138 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003139 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003140 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003141 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003142 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3143 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003144 message1.setData("",
3145 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003146 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003147 message2.setData("",
3148 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003149
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003150 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003151 .setContentTitle("foo")
3152 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3153 .setStyle(new Notification.MessagingStyle("")
3154 .addMessage(message1)
3155 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003156 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3157 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003158
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003159 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003160 reset(mUgm);
3161 reset(mUgmInternal);
3162 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003163 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
3164 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003165 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003166 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003167 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003168 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3169
3170 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003171 .setContentTitle("foo")
3172 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3173 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003174 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3175 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003176
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003177 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003178 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003179 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
3180 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003181 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3182 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003183
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003184 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003185 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003186 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
3187 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003188 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003189 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003190
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003191 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003192 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003193 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
3194 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003195 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003196 anyInt(), anyInt());
3197 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003198
3199 @Test
Robin Leed107af62018-04-27 13:55:56 +02003200 public void testVisitUris() throws Exception {
3201 final Uri audioContents = Uri.parse("content://com.example/audio");
3202 final Uri backgroundImage = Uri.parse("content://com.example/background");
3203
3204 Bundle extras = new Bundle();
3205 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3206 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3207
3208 Notification n = new Notification.Builder(mContext, "a")
3209 .setContentTitle("notification with uris")
3210 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3211 .addExtras(extras)
3212 .build();
3213
3214 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3215 n.visitUris(visitor);
3216 verify(visitor, times(1)).accept(eq(audioContents));
3217 verify(visitor, times(1)).accept(eq(backgroundImage));
3218 }
3219
3220 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003221 public void testSetNotificationPolicy_preP_setOldFields() {
3222 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3223 mService.mZenModeHelper = mZenModeHelper;
3224 NotificationManager.Policy userPolicy =
3225 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3226 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3227
3228 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3229 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3230
3231 int expected = SUPPRESSED_EFFECT_BADGE
3232 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003233 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3234 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003235 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3236
3237 assertEquals(expected, actual);
3238 }
3239
3240 @Test
3241 public void testSetNotificationPolicy_preP_setNewFields() {
3242 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3243 mService.mZenModeHelper = mZenModeHelper;
3244 NotificationManager.Policy userPolicy =
3245 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3246 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3247
3248 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3249 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3250
3251 int expected = SUPPRESSED_EFFECT_BADGE;
3252 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3253
3254 assertEquals(expected, actual);
3255 }
3256
3257 @Test
3258 public void testSetNotificationPolicy_preP_setOldNewFields() {
3259 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3260 mService.mZenModeHelper = mZenModeHelper;
3261 NotificationManager.Policy userPolicy =
3262 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3263 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3264
3265 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3266 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3267
3268 int expected =
3269 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3270 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3271
3272 assertEquals(expected, actual);
3273 }
3274
3275 @Test
3276 public void testSetNotificationPolicy_P_setOldFields() {
3277 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3278 mService.mZenModeHelper = mZenModeHelper;
3279 NotificationManager.Policy userPolicy =
3280 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3281 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3282
3283 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3284 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3285
3286 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3287 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3288 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3289 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3290
3291 assertEquals(expected, actual);
3292 }
3293
3294 @Test
3295 public void testSetNotificationPolicy_P_setNewFields() {
3296 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3297 mService.mZenModeHelper = mZenModeHelper;
3298 NotificationManager.Policy userPolicy =
3299 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3300 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3301
3302 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3303 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3304 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3305
3306 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3307 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3308 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3309 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3310
3311 assertEquals(expected, actual);
3312 }
3313
3314 @Test
3315 public void testSetNotificationPolicy_P_setOldNewFields() {
3316 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3317 mService.mZenModeHelper = mZenModeHelper;
3318 NotificationManager.Policy userPolicy =
3319 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3320 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3321
3322 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3323 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3324
3325 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3326 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3327
3328 assertEquals(expected, actual);
3329
3330 appPolicy = new NotificationManager.Policy(0, 0, 0,
3331 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3332 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3333
3334 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3335 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3336 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3337
3338 assertEquals(expected, actual);
3339 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003340
3341 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003342 public void testVisualDifference_foreground() {
3343 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3344 .setContentTitle("foo");
3345 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3346 nb1.build(), new UserHandle(mUid), null, 0);
3347 NotificationRecord r1 =
3348 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3349
3350 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3351 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3352 .setContentTitle("bar");
3353 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3354 nb2.build(), new UserHandle(mUid), null, 0);
3355 NotificationRecord r2 =
3356 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3357
3358 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3359 }
3360
3361 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003362 public void testVisualDifference_diffTitle() {
3363 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3364 .setContentTitle("foo");
3365 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3366 nb1.build(), new UserHandle(mUid), null, 0);
3367 NotificationRecord r1 =
3368 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3369
3370 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3371 .setContentTitle("bar");
3372 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3373 nb2.build(), new UserHandle(mUid), null, 0);
3374 NotificationRecord r2 =
3375 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3376
3377 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3378 }
3379
3380 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003381 public void testVisualDifference_inboxStyle() {
3382 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3383 .setStyle(new Notification.InboxStyle()
3384 .addLine("line1").addLine("line2"));
3385 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3386 nb1.build(), new UserHandle(mUid), null, 0);
3387 NotificationRecord r1 =
3388 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3389
3390 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3391 .setStyle(new Notification.InboxStyle()
3392 .addLine("line1").addLine("line2_changed"));
3393 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3394 nb2.build(), new UserHandle(mUid), null, 0);
3395 NotificationRecord r2 =
3396 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3397
3398 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3399
3400 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3401 .setStyle(new Notification.InboxStyle()
3402 .addLine("line1"));
3403 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3404 nb3.build(), new UserHandle(mUid), null, 0);
3405 NotificationRecord r3 =
3406 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3407
3408 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3409
3410 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3411 .setStyle(new Notification.InboxStyle()
3412 .addLine("line1").addLine("line2").addLine("line3"));
3413 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3414 nb4.build(), new UserHandle(mUid), null, 0);
3415 NotificationRecord r4 =
3416 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3417
3418 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3419
3420 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3421 .setContentText("not an inbox");
3422 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3423 nb5.build(), new UserHandle(mUid), null, 0);
3424 NotificationRecord r5 =
3425 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3426
3427 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3428 }
3429
3430 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003431 public void testVisualDifference_diffText() {
3432 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3433 .setContentText("foo");
3434 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3435 nb1.build(), new UserHandle(mUid), null, 0);
3436 NotificationRecord r1 =
3437 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3438
3439 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3440 .setContentText("bar");
3441 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3442 nb2.build(), new UserHandle(mUid), null, 0);
3443 NotificationRecord r2 =
3444 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3445
3446 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3447 }
3448
3449 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003450 public void testVisualDifference_sameText() {
3451 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3452 .setContentText("foo");
3453 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3454 nb1.build(), new UserHandle(mUid), null, 0);
3455 NotificationRecord r1 =
3456 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3457
3458 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3459 .setContentText("foo");
3460 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3461 nb2.build(), new UserHandle(mUid), null, 0);
3462 NotificationRecord r2 =
3463 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3464
3465 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3466 }
3467
3468 @Test
3469 public void testVisualDifference_sameTextButStyled() {
3470 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3471 .setContentText(Html.fromHtml("<b>foo</b>"));
3472 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3473 nb1.build(), new UserHandle(mUid), null, 0);
3474 NotificationRecord r1 =
3475 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3476
3477 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3478 .setContentText(Html.fromHtml("<b>foo</b>"));
3479 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3480 nb2.build(), new UserHandle(mUid), null, 0);
3481 NotificationRecord r2 =
3482 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3483
3484 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3485 }
3486
3487 @Test
3488 public void testVisualDifference_diffTextButStyled() {
3489 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3490 .setContentText(Html.fromHtml("<b>foo</b>"));
3491 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3492 nb1.build(), new UserHandle(mUid), null, 0);
3493 NotificationRecord r1 =
3494 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3495
3496 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3497 .setContentText(Html.fromHtml("<b>bar</b>"));
3498 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3499 nb2.build(), new UserHandle(mUid), null, 0);
3500 NotificationRecord r2 =
3501 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3502
3503 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3504 }
3505
3506 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003507 public void testVisualDifference_diffProgress() {
3508 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3509 .setProgress(100, 90, false);
3510 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3511 nb1.build(), new UserHandle(mUid), null, 0);
3512 NotificationRecord r1 =
3513 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3514
3515 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3516 .setProgress(100, 100, false);
3517 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3518 nb2.build(), new UserHandle(mUid), null, 0);
3519 NotificationRecord r2 =
3520 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3521
3522 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3523 }
3524
3525 @Test
3526 public void testVisualDifference_diffProgressNotDone() {
3527 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3528 .setProgress(100, 90, false);
3529 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3530 nb1.build(), new UserHandle(mUid), null, 0);
3531 NotificationRecord r1 =
3532 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3533
3534 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3535 .setProgress(100, 91, false);
3536 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3537 nb2.build(), new UserHandle(mUid), null, 0);
3538 NotificationRecord r2 =
3539 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3540
3541 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3542 }
Beverly5a20a5e2018-03-06 15:02:44 -05003543
3544 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003545 public void testVisualDifference_sameProgressStillDone() {
3546 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3547 .setProgress(100, 100, false);
3548 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3549 nb1.build(), new UserHandle(mUid), null, 0);
3550 NotificationRecord r1 =
3551 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3552
3553 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3554 .setProgress(100, 100, false);
3555 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3556 nb2.build(), new UserHandle(mUid), null, 0);
3557 NotificationRecord r2 =
3558 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3559
3560 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3561 }
3562
3563 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003564 public void testVisualDifference_summary() {
3565 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3566 .setGroup("bananas")
3567 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3568 .setContentText("foo");
3569 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3570 nb1.build(), new UserHandle(mUid), null, 0);
3571 NotificationRecord r1 =
3572 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3573
3574 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3575 .setGroup("bananas")
3576 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3577 .setContentText("bar");
3578 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3579 nb2.build(), new UserHandle(mUid), null, 0);
3580 NotificationRecord r2 =
3581 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3582
3583 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3584 }
3585
3586 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003587 public void testVisualDifference_summaryNewNotification() {
3588 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3589 .setGroup("bananas")
3590 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3591 .setContentText("bar");
3592 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3593 nb2.build(), new UserHandle(mUid), null, 0);
3594 NotificationRecord r2 =
3595 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3596
3597 assertFalse(mService.isVisuallyInterruptive(null, r2));
3598 }
3599
3600 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003601 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3602 // post 2 notification from this package
3603 final NotificationRecord notif1 = generateNotificationRecord(
3604 mTestNotificationChannel, 1, null, true);
3605 final NotificationRecord notif2 = generateNotificationRecord(
3606 mTestNotificationChannel, 2, null, false);
3607 mService.addNotification(notif1);
3608 mService.addNotification(notif2);
3609
3610 // on broadcast, hide the 2 notifications
3611 mService.simulatePackageSuspendBroadcast(true, PKG);
3612 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3613 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3614 assertEquals(2, captorHide.getValue().size());
3615
3616 // on broadcast, unhide the 2 notifications
3617 mService.simulatePackageSuspendBroadcast(false, PKG);
3618 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3619 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3620 assertEquals(2, captorUnhide.getValue().size());
3621 }
3622
3623 @Test
3624 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3625 // post 2 notification from this package
3626 final NotificationRecord notif1 = generateNotificationRecord(
3627 mTestNotificationChannel, 1, null, true);
3628 final NotificationRecord notif2 = generateNotificationRecord(
3629 mTestNotificationChannel, 2, null, false);
3630 mService.addNotification(notif1);
3631 mService.addNotification(notif2);
3632
3633 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3634 mService.simulatePackageSuspendBroadcast(true, "test_package");
3635 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3636 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3637 assertEquals(0, captor.getValue().size());
3638 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003639
3640 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003641 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3642 // Post 2 notifications from 2 packages
3643 NotificationRecord pkgA = new NotificationRecord(mContext,
3644 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3645 mService.addNotification(pkgA);
3646 NotificationRecord pkgB = new NotificationRecord(mContext,
3647 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3648 mService.addNotification(pkgB);
3649
3650 // on broadcast, hide one of the packages
3651 mService.simulatePackageDistractionBroadcast(
3652 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3653 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3654 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3655 assertEquals(1, captorHide.getValue().size());
3656 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3657
3658 // on broadcast, unhide the package
3659 mService.simulatePackageDistractionBroadcast(
3660 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3661 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3662 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3663 assertEquals(1, captorUnhide.getValue().size());
3664 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3665 }
3666
3667 @Test
3668 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3669 // Post 2 notifications from 2 packages
3670 NotificationRecord pkgA = new NotificationRecord(mContext,
3671 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3672 mService.addNotification(pkgA);
3673 NotificationRecord pkgB = new NotificationRecord(mContext,
3674 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3675 mService.addNotification(pkgB);
3676
3677 // on broadcast, hide one of the packages
3678 mService.simulatePackageDistractionBroadcast(
3679 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3680 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003681
3682 // should be called only once.
3683 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003684 assertEquals(2, captorHide.getValue().size());
3685 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3686 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3687
3688 // on broadcast, unhide the package
3689 mService.simulatePackageDistractionBroadcast(
3690 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3691 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003692
3693 // should be called only once.
3694 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003695 assertEquals(2, captorUnhide.getValue().size());
3696 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3697 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3698 }
3699
3700 @Test
3701 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3702 // post notification from this package
3703 final NotificationRecord notif1 = generateNotificationRecord(
3704 mTestNotificationChannel, 1, null, true);
3705 mService.addNotification(notif1);
3706
3707 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3708 mService.simulatePackageDistractionBroadcast(
3709 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3710 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3711 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3712 assertEquals(0, captor.getValue().size());
3713 }
3714
3715 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003716 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3717 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3718 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3719 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3720 .thenReturn(new String[] {"a", "b", "c"});
3721 when(mContext.getResources()).thenReturn(mResources);
3722
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003723 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003724 }
3725
3726 @Test
3727 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3728 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3729 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3730 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3731 .thenReturn(new String[] {"a", "b", "c"});
3732 when(mContext.getResources()).thenReturn(mResources);
3733
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003734 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003735 }
3736
3737 @Test
3738 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3739 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3740 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3741 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3742 .thenReturn(new String[] {"a", "b", "c"});
3743 when(mContext.getResources()).thenReturn(mResources);
3744
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003745 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003746 }
3747
3748 @Test
3749 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3750 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3751 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3752 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3753 .thenReturn(new String[] {"a", "b", "c"});
3754 when(mContext.getResources()).thenReturn(mResources);
3755
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003756 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003757 }
3758
3759 @Test
3760 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3761 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3762 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3763 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3764 .thenReturn(new String[] {"a", "b", "c"});
3765 when(mContext.getResources()).thenReturn(mResources);
3766
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003767 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003768 }
3769
3770 @Test
3771 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
3772 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3773 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3774 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3775 .thenReturn(new String[] {"a", "b", "c"});
3776 when(mContext.getResources()).thenReturn(mResources);
3777
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003778 assertEquals(true, mService.canUseManagedServices("d", 0, null));
3779 }
3780
3781 @Test
3782 public void testCanUseManagedServices_hasPermission() throws Exception {
3783 when(mPackageManager.checkPermission("perm", "pkg", 0))
3784 .thenReturn(PackageManager.PERMISSION_GRANTED);
3785
3786 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
3787 }
3788
3789 @Test
3790 public void testCanUseManagedServices_noPermission() throws Exception {
3791 when(mPackageManager.checkPermission("perm", "pkg", 0))
3792 .thenReturn(PackageManager.PERMISSION_DENIED);
3793
3794 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
3795 }
3796
3797 @Test
3798 public void testCanUseManagedServices_permDoesNotMatter() {
3799 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003800 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003801
3802 @Test
3803 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
3804 final NotificationRecord r = generateNotificationRecord(
3805 mTestNotificationChannel, 1, null, true);
3806 r.setTextChanged(true);
3807 mService.addNotification(r);
3808
3809 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
3810 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
3811 new NotificationVisibility[]{});
3812
3813 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3814 }
3815
3816 @Test
3817 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
3818 throws RemoteException {
3819 final NotificationRecord r = generateNotificationRecord(
3820 mTestNotificationChannel, 1, null, true);
3821 r.setTextChanged(true);
3822 mService.addNotification(r);
3823
3824 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
3825
3826 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3827 }
3828
3829 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003830 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003831 throws RemoteException {
3832 final NotificationRecord r = generateNotificationRecord(
3833 mTestNotificationChannel, 1, null, true);
3834 r.setInterruptive(true);
3835 mService.addNotification(r);
3836
3837 mService.maybeRecordInterruptionLocked(r);
3838 mService.maybeRecordInterruptionLocked(r);
3839
3840 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
3841 anyString(), anyString(), anyInt());
3842 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003843
3844 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08003845 public void testBubble() throws Exception {
3846 mBinderService.setBubblesAllowed(PKG, mUid, false);
3847 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05003848 }
3849
3850 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08003851 public void testUserApprovedBubblesForPackage() throws Exception {
3852 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3853 mBinderService.setBubblesAllowed(PKG, mUid, true);
3854 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3855 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3856 }
3857
3858 @Test
3859 public void testUserRejectsBubblesForPackage() throws Exception {
3860 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3861 mBinderService.setBubblesAllowed(PKG, mUid, false);
3862 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3863 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3864 }
3865
3866 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003867 public void testIsCallerInstantApp_primaryUser() throws Exception {
3868 ApplicationInfo info = new ApplicationInfo();
3869 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3870 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04003871 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003872
Julia Reynolds268647a2018-10-25 16:54:27 -04003873 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003874
3875 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04003876 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003877 }
3878
3879 @Test
3880 public void testIsCallerInstantApp_secondaryUser() throws Exception {
3881 ApplicationInfo info = new ApplicationInfo();
3882 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3883 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3884 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04003885 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003886
Julia Reynolds268647a2018-10-25 16:54:27 -04003887 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003888 }
3889
3890 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04003891 public void testIsCallerInstantApp_userAllNotification() throws Exception {
3892 ApplicationInfo info = new ApplicationInfo();
3893 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3894 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
3895 .thenReturn(info);
3896 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3897
3898 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
3899
3900 info.privateFlags = 0;
3901 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
3902 }
3903
3904 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003905 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
3906 ApplicationInfo info = new ApplicationInfo();
3907 info.uid = Binder.getCallingUid();
3908 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3909 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3910
3911 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
3912
3913 assertEquals(info.uid, actualUid);
3914 }
3915
3916 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003917 public void testResolveNotificationUid_sameApp() throws Exception {
3918 ApplicationInfo info = new ApplicationInfo();
3919 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04003920 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003921
3922 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
3923
3924 assertEquals(info.uid, actualUid);
3925 }
3926
3927 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003928 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003929 ApplicationInfo info = new ApplicationInfo();
3930 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003931 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003932
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003933 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
3934
3935 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003936 }
3937
3938 @Test
3939 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
3940 ApplicationInfo info = new ApplicationInfo();
3941 info.uid = 1356347;
3942 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
3943
3944 try {
3945 mService.resolveNotificationUid("caller", "caller", 9, 0);
3946 fail("Incorrect uid didn't throw security exception");
3947 } catch (SecurityException e) {
3948 // yay
3949 }
3950 }
3951
3952 @Test
3953 public void testResolveNotificationUid_delegateAllowed() throws Exception {
3954 int expectedUid = 123;
3955
3956 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3957 mService.setPreferencesHelper(mPreferencesHelper);
3958 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
3959 .thenReturn(true);
3960
3961 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
3962 }
3963
3964 @Test
3965 public void testResolveNotificationUid_androidAllowed() throws Exception {
3966 int expectedUid = 123;
3967
3968 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3969 // no delegate
3970
3971 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
3972 }
3973
3974 @Test
3975 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
3976 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
3977 // no delegate
3978
3979 try {
3980 mService.resolveNotificationUid("caller", "target", 9, 0);
3981 fail("Incorrect uid didn't throw security exception");
3982 } catch (SecurityException e) {
3983 // yay
3984 }
3985 }
Julia Reynolds564273f2018-09-13 15:53:11 -04003986
3987 @Test
3988 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
3989 Notification n = new Notification.Builder(mContext, "").build();
3990 n.flags |= FLAG_FOREGROUND_SERVICE;
3991
3992 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3993 n, new UserHandle(mUid), null, 0);
3994 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3995
3996 mService.addEnqueuedNotification(r);
3997
3998 mInternalService.removeForegroundServiceFlagFromNotification(
3999 PKG, r.sbn.getId(), r.sbn.getUserId());
4000
4001 waitForIdle();
4002
4003 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4004 }
4005
4006 @Test
4007 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4008 Notification n = new Notification.Builder(mContext, "").build();
4009 n.flags |= FLAG_FOREGROUND_SERVICE;
4010
4011 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4012 n, new UserHandle(mUid), null, 0);
4013 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4014
4015 mService.addNotification(r);
4016
4017 mInternalService.removeForegroundServiceFlagFromNotification(
4018 PKG, r.sbn.getId(), r.sbn.getUserId());
4019
4020 waitForIdle();
4021
4022 ArgumentCaptor<NotificationRecord> captor =
4023 ArgumentCaptor.forClass(NotificationRecord.class);
4024 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4025
4026 assertEquals(0, captor.getValue().getNotification().flags);
4027 }
Beverly58b24532018-10-02 09:08:23 -04004028
4029 @Test
4030 public void testAllowForegroundToasts() throws Exception {
4031 final String testPackage = "testPackageName";
4032 assertEquals(0, mService.mToastQueue.size());
4033 mService.isSystemUid = false;
4034
4035 // package is not suspended
4036 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4037 .thenReturn(false);
4038
4039 // notifications from this package are blocked by the user
4040 mService.setPreferencesHelper(mPreferencesHelper);
4041 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4042
4043 // this app is in the foreground
4044 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4045
4046 // enqueue toast -> toast should still enqueue
4047 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4048 new TestableToastCallback(), 2000, 0);
4049 assertEquals(1, mService.mToastQueue.size());
4050 }
4051
4052 @Test
4053 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4054 final String testPackage = "testPackageName";
4055 assertEquals(0, mService.mToastQueue.size());
4056 mService.isSystemUid = false;
4057
4058 // package is suspended
4059 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4060 .thenReturn(true);
4061
4062 // notifications from this package are NOT blocked by the user
4063 mService.setPreferencesHelper(mPreferencesHelper);
4064 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4065
4066 // enqueue toast -> no toasts enqueued
4067 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4068 new TestableToastCallback(), 2000, 0);
4069 assertEquals(0, mService.mToastQueue.size());
4070 }
4071
4072 @Test
4073 public void testDisallowToastsFromBlockedApps() throws Exception {
4074 final String testPackage = "testPackageName";
4075 assertEquals(0, mService.mToastQueue.size());
4076 mService.isSystemUid = false;
4077
4078 // package is not suspended
4079 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4080 .thenReturn(false);
4081
4082 // notifications from this package are blocked by the user
4083 mService.setPreferencesHelper(mPreferencesHelper);
4084 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4085
4086 // this app is NOT in the foreground
4087 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4088
4089 // enqueue toast -> no toasts enqueued
4090 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4091 new TestableToastCallback(), 2000, 0);
4092 assertEquals(0, mService.mToastQueue.size());
4093 }
4094
4095 @Test
4096 public void testAlwaysAllowSystemToasts() throws Exception {
4097 final String testPackage = "testPackageName";
4098 assertEquals(0, mService.mToastQueue.size());
4099 mService.isSystemUid = true;
4100
4101 // package is suspended
4102 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4103 .thenReturn(true);
4104
4105 // notifications from this package ARE blocked by the user
4106 mService.setPreferencesHelper(mPreferencesHelper);
4107 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4108
4109 // this app is NOT in the foreground
4110 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4111
4112 // enqueue toast -> system toast can still be enqueued
4113 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4114 new TestableToastCallback(), 2000, 0);
4115 assertEquals(1, mService.mToastQueue.size());
4116 }
Tony Mak29996702018-11-26 16:23:34 +00004117
4118 @Test
4119 public void testOnNotificationSmartReplySent() {
4120 final int replyIndex = 2;
4121 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004122 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004123 final boolean generatedByAssistant = true;
4124
4125 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004126 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004127 mService.addNotification(r);
4128
4129 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004130 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4131 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004132 verify(mAssistants).notifyAssistantSuggestedReplySent(
4133 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4134 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004135
4136 @Test
4137 public void testOnNotificationActionClick() {
4138 final int actionIndex = 2;
4139 final Notification.Action action =
4140 new Notification.Action.Builder(null, "text", null).build();
4141 final boolean generatedByAssistant = false;
4142
4143 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4144 mService.addNotification(r);
4145
4146 NotificationVisibility notificationVisibility =
4147 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4148 mService.mNotificationDelegate.onNotificationActionClick(
4149 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4150 generatedByAssistant);
4151 verify(mAssistants).notifyAssistantActionClicked(
4152 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4153 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004154
4155 @Test
4156 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4157 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4158 mService.addNotification(r);
4159
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004160 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4161 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004162 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4163 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4164 };
4165 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4166 new NotificationVisibility[0]);
4167
4168 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4169 }
4170
4171 @Test
4172 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4173 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4174 mService.addNotification(r);
4175
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004176 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4177 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004178
4179 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4180 }
4181
4182 @Test
4183 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4184 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4185 mService.addNotification(r);
4186
Julia Reynolds95334132018-12-19 11:15:35 -05004187 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004188 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4189 };
4190 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4191 new NotificationVisibility[0]);
4192
4193 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4194 }
Julia Reynolds95334132018-12-19 11:15:35 -05004195
Colin Cross1f4620a2019-12-18 17:16:36 -08004196 @Test
Julia Reynolds95334132018-12-19 11:15:35 -05004197 public void testReportSeen_delegated() {
4198 Notification.Builder nb =
4199 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4200 .setContentTitle("foo")
4201 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4202
4203 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4204 nb.build(), new UserHandle(mUid), null, 0);
4205 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4206
4207 mService.reportSeen(r);
4208 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4209
4210 }
4211
4212 @Test
4213 public void testReportSeen_notDelegated() {
4214 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4215
4216 mService.reportSeen(r);
4217 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4218 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004219
4220 @Test
4221 public void testNotificationStats_notificationError() {
4222 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4223 mService.addNotification(r);
4224
4225 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4226 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4227 new UserHandle(mUid), null, 0);
4228 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4229 mService.addEnqueuedNotification(update);
4230 assertNull(update.sbn.getNotification().getSmallIcon());
4231
4232 NotificationManagerService.PostNotificationRunnable runnable =
4233 mService.new PostNotificationRunnable(update.getKey());
4234 runnable.run();
4235 waitForIdle();
4236
4237 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4238 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4239 assertNotNull(captor.getValue());
4240 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004241
4242 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004243 public void testCanNotifyAsUser_crossUser() throws Exception {
4244 // same user no problem
4245 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4246
4247 // cross user, no permission, problem
4248 try {
4249 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4250 fail("Should not be callable cross user without cross user permission");
4251 } catch (SecurityException e) {
4252 // good
4253 }
4254
4255 // cross user, with permission, no problem
4256 TestablePermissions perms = mContext.getTestablePermissions();
4257 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4258 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4259 }
4260
4261 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004262 public void testgetNotificationChannels_crossUser() throws Exception {
4263 // same user no problem
4264 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4265
4266 // cross user, no permission, problem
4267 try {
4268 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4269 fail("Should not be callable cross user without cross user permission");
4270 } catch (SecurityException e) {
4271 // good
4272 }
4273
4274 // cross user, with permission, no problem
4275 TestablePermissions perms = mContext.getTestablePermissions();
4276 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4277 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4278 }
4279
4280 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004281 public void setDefaultAssistantForUser_fromConfigXml() {
4282 clearDeviceConfig();
4283 ComponentName xmlConfig = new ComponentName("config", "xml");
4284 when(mResources
4285 .getString(
4286 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4287 .thenReturn(xmlConfig.flattenToString());
4288 when(mContext.getResources()).thenReturn(mResources);
4289 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4290 .thenReturn(Collections.singleton(xmlConfig));
4291 mService.setNotificationAssistantAccessGrantedCallback(
4292 mNotificationAssistantAccessGrantedCallback);
4293
4294 mService.setDefaultAssistantForUser(0);
4295
4296 verify(mNotificationAssistantAccessGrantedCallback)
4297 .onGranted(eq(xmlConfig), eq(0), eq(true));
4298 }
4299
4300 @Test
4301 public void setDefaultAssistantForUser_fromDeviceConfig() {
4302 ComponentName xmlConfig = new ComponentName("xml", "config");
4303 ComponentName deviceConfig = new ComponentName("device", "config");
4304 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4305 when(mResources
4306 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4307 .thenReturn(xmlConfig.flattenToString());
4308 when(mContext.getResources()).thenReturn(mResources);
4309 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4310 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
4311 mService.setNotificationAssistantAccessGrantedCallback(
4312 mNotificationAssistantAccessGrantedCallback);
4313
4314 mService.setDefaultAssistantForUser(0);
4315
4316 verify(mNotificationAssistantAccessGrantedCallback)
4317 .onGranted(eq(deviceConfig), eq(0), eq(true));
4318 }
4319
4320 @Test
4321 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4322 ComponentName xmlConfig = new ComponentName("xml", "config");
4323 ComponentName deviceConfig = new ComponentName("device", "config");
4324 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4325 when(mResources
4326 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4327 .thenReturn(xmlConfig.flattenToString());
4328 when(mContext.getResources()).thenReturn(mResources);
4329 // Only xmlConfig is valid, deviceConfig is not.
4330 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4331 .thenReturn(Collections.singleton(xmlConfig));
4332 mService.setNotificationAssistantAccessGrantedCallback(
4333 mNotificationAssistantAccessGrantedCallback);
4334
4335 mService.setDefaultAssistantForUser(0);
4336
4337 verify(mNotificationAssistantAccessGrantedCallback)
4338 .onGranted(eq(xmlConfig), eq(0), eq(true));
4339 }
4340
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004341 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004342 public void testFlagBubble() throws RemoteException {
4343 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004344 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004345
4346 // Notif with bubble metadata but not our other misc requirements
4347 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4348 null /* tvExtender */, true /* isBubble */);
4349
4350 // Say we're foreground
4351 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4352 IMPORTANCE_FOREGROUND);
4353
4354 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4355 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4356 waitForIdle();
4357
4358 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4359 assertEquals(1, notifs.length);
4360 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4361 assertTrue(mService.getNotificationRecord(
4362 nr.sbn.getKey()).getNotification().isBubbleNotification());
4363 }
4364
4365 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004366 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4367 // Bubbles are allowed!
4368 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4369
4370 // Notif with bubble metadata but not our other misc requirements
4371 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4372 null /* tvExtender */, true /* isBubble */);
4373
4374 // Say we're foreground
4375 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4376 IMPORTANCE_FOREGROUND);
4377
4378 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4379 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4380 waitForIdle();
4381
4382 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4383 assertEquals(1, notifs.length);
4384 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4385 assertFalse(mService.getNotificationRecord(
4386 nr.sbn.getKey()).getNotification().isBubbleNotification());
4387 }
4388
4389 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004390 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004391 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004392 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004393
Mady Mellorbe797962019-04-01 16:04:24 -07004394 // Notif with bubble metadata but not our other misc requirements
4395 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4396 null /* tvExtender */, true /* isBubble */);
4397
4398 // Say we're foreground
4399 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4400 IMPORTANCE_FOREGROUND);
4401
4402 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4403 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4404 waitForIdle();
4405
4406 // yes allowed, yes foreground, yes bubble
4407 assertTrue(mService.getNotificationRecord(
4408 nr.sbn.getKey()).getNotification().isBubbleNotification());
4409 }
4410
4411 @Test
4412 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4413 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004414 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004415
4416 // Notif with bubble metadata but not our other misc requirements
4417 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4418 null /* tvExtender */, true /* isBubble */);
4419
4420 // Make sure we're NOT foreground
4421 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4422 IMPORTANCE_VISIBLE);
4423
4424 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4425 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4426 waitForIdle();
4427
4428 // yes allowed but NOT foreground, no bubble
4429 assertFalse(mService.getNotificationRecord(
4430 nr.sbn.getKey()).getNotification().isBubbleNotification());
4431 }
4432
4433 @Test
4434 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4435 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004436 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004437
4438 // Notif with bubble metadata but not our other misc requirements
4439 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4440 null /* tvExtender */, true /* isBubble */);
4441
4442 // Send notif when we're foreground
4443 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4444 IMPORTANCE_FOREGROUND);
4445 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4446 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4447 waitForIdle();
4448
4449 // yes allowed, yes foreground, yes bubble
4450 assertTrue(mService.getNotificationRecord(
4451 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4452
4453 // Send a new update when we're not foreground
4454 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4455 null /* tvExtender */, true /* isBubble */);
4456
4457 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4458 IMPORTANCE_VISIBLE);
4459 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4460 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4461 waitForIdle();
4462
4463 // yes allowed, previously foreground / flagged, yes bubble
4464 assertTrue(mService.getNotificationRecord(
4465 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4466
4467 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4468 assertEquals(1, notifs2.length);
4469 assertEquals(1, mService.getNotificationRecordCount());
4470 }
4471
4472 @Test
4473 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4474 throws RemoteException {
4475 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004476 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004477
4478 // Notif with bubble metadata but not our other misc requirements
4479 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4480 null /* tvExtender */, true /* isBubble */);
4481
4482 // Send notif when we're foreground
4483 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4484 IMPORTANCE_FOREGROUND);
4485 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4486 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4487 waitForIdle();
4488
4489 // yes allowed, yes foreground, yes bubble
4490 assertTrue(mService.getNotificationRecord(
4491 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4492
4493 // Remove the bubble
4494 mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(),
4495 nr1.sbn.getUserId());
4496 waitForIdle();
4497
4498 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4499 assertEquals(0, notifs.length);
4500 assertEquals(0, mService.getNotificationRecordCount());
4501
4502 // Send a new update when we're not foreground
4503 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4504 null /* tvExtender */, true /* isBubble */);
4505
4506 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4507 IMPORTANCE_VISIBLE);
4508 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4509 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4510 waitForIdle();
4511
4512 // yes allowed, but was removed & no foreground, so no bubble
4513 assertFalse(mService.getNotificationRecord(
4514 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4515
4516 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4517 assertEquals(1, notifs2.length);
4518 assertEquals(1, mService.getNotificationRecordCount());
4519 }
4520
4521 @Test
4522 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4523 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004524 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004525
4526 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004527 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004528 // Give it a person
4529 Person person = new Person.Builder()
4530 .setName("bubblebot")
4531 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004532 // It needs remote input to be bubble-able
4533 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4534 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4535 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4536 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4537 inputIntent).addRemoteInput(remoteInput)
4538 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004539 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004540 Notification.Builder nb = new Notification.Builder(mContext,
4541 mTestNotificationChannel.getId())
4542 .setContentTitle("foo")
4543 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004544 .setStyle(new Notification.MessagingStyle(person)
4545 .setConversationTitle("Bubble Chat")
4546 .addMessage("Hello?",
4547 SystemClock.currentThreadTimeMillis() - 300000, person)
4548 .addMessage("Is it me you're looking for?",
4549 SystemClock.currentThreadTimeMillis(), person)
4550 )
Mady Mellora10448e2019-04-26 13:50:58 -07004551 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -07004552 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4553
4554 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4555 nb.build(), new UserHandle(mUid), null, 0);
4556 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4557
4558 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4559 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4560 waitForIdle();
4561
4562 // yes allowed, yes messaging, yes bubble
4563 assertTrue(mService.getNotificationRecord(
4564 sbn.getKey()).getNotification().isBubbleNotification());
4565 }
4566
4567 @Test
4568 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4569 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004570 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004571
4572 // Give it bubble metadata
4573 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4574 // Give it a person
4575 Person person = new Person.Builder()
4576 .setName("bubblebot")
4577 .build();
4578 // Make it a phone call
4579 Notification.Builder nb = new Notification.Builder(mContext,
4580 mTestNotificationChannel.getId())
4581 .setCategory(CATEGORY_CALL)
4582 .addPerson(person)
4583 .setContentTitle("foo")
4584 .setBubbleMetadata(data)
4585 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4586
4587 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4588 nb.build(), new UserHandle(mUid), null, 0);
4589 // Make sure it has foreground service
4590 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4591 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4592
4593 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4594 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4595 waitForIdle();
4596
4597 // yes phone call, yes person, yes foreground service, yes bubble
4598 assertTrue(mService.getNotificationRecord(
4599 sbn.getKey()).getNotification().isBubbleNotification());
4600 }
4601
4602 @Test
4603 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4604 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004605 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004606
4607 // Give it bubble metadata
4608 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4609 // Give it a person
4610 Person person = new Person.Builder()
4611 .setName("bubblebot")
4612 .build();
4613 // Make it a phone call
4614 Notification.Builder nb = new Notification.Builder(mContext,
4615 mTestNotificationChannel.getId())
4616 .setCategory(CATEGORY_CALL)
4617 .addPerson(person)
4618 .setContentTitle("foo")
4619 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004620 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4621
4622 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4623 nb.build(), new UserHandle(mUid), null, 0);
4624 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4625
4626 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4627 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4628 waitForIdle();
4629
Mady Mellorbe797962019-04-01 16:04:24 -07004630 // yes phone call, yes person, NO foreground service, no bubble
4631 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004632 sbn.getKey()).getNotification().isBubbleNotification());
4633 }
4634
4635 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004636 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4637 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004638 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004639
4640 // Give it bubble metadata
4641 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4642 // Make it a phone call
4643 Notification.Builder nb = new Notification.Builder(mContext,
4644 mTestNotificationChannel.getId())
4645 .setCategory(CATEGORY_CALL)
4646 .setContentTitle("foo")
4647 .setBubbleMetadata(data)
4648 .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 // Make sure it has foreground service
4653 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4654 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4655
4656 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4657 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4658 waitForIdle();
4659
4660 // yes phone call, yes foreground service, BUT NO person, no bubble
4661 assertFalse(mService.getNotificationRecord(
4662 sbn.getKey()).getNotification().isBubbleNotification());
4663 }
4664
4665 @Test
4666 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4667 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004668 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004669
4670 // Give it bubble metadata
4671 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4672 // Give it a person
4673 Person person = new Person.Builder()
4674 .setName("bubblebot")
4675 .build();
4676 // No category
4677 Notification.Builder nb = new Notification.Builder(mContext,
4678 mTestNotificationChannel.getId())
4679 .addPerson(person)
4680 .setContentTitle("foo")
4681 .setBubbleMetadata(data)
4682 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4683
4684 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4685 nb.build(), new UserHandle(mUid), null, 0);
4686 // Make sure it has foreground service
4687 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4688 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4689
4690 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4691 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4692 waitForIdle();
4693
4694 // yes person, yes foreground service, BUT NO call, no bubble
4695 assertFalse(mService.getNotificationRecord(
4696 sbn.getKey()).getNotification().isBubbleNotification());
4697 }
4698
4699 @Test
4700 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004701 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004702 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004703
Mady Mellorbe797962019-04-01 16:04:24 -07004704 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004705 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004706 // Give it a person
4707 Person person = new Person.Builder()
4708 .setName("bubblebot")
4709 .build();
4710 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004711 Notification.Builder nb = new Notification.Builder(mContext,
4712 mTestNotificationChannel.getId())
4713 .setContentTitle("foo")
4714 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004715 .setStyle(new Notification.MessagingStyle(person)
4716 .setConversationTitle("Bubble Chat")
4717 .addMessage("Hello?",
4718 SystemClock.currentThreadTimeMillis() - 300000, person)
4719 .addMessage("Is it me you're looking for?",
4720 SystemClock.currentThreadTimeMillis(), person)
4721 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004722 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4723
4724 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4725 nb.build(), new UserHandle(mUid), null, 0);
4726 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4727
4728 // Post the notification
4729 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4730 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4731 waitForIdle();
4732
4733 // not allowed, no bubble
4734 assertFalse(mService.getNotificationRecord(
4735 sbn.getKey()).getNotification().isBubbleNotification());
4736 }
4737
4738 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004739 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004740 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004741 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004742
4743 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07004744 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004745
4746 // Post the notification
Mady Mellorbe797962019-04-01 16:04:24 -07004747 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004748 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4749 waitForIdle();
4750
4751 // no bubble metadata, no bubble
4752 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07004753 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004754 }
4755
4756 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004757 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004758 // Bubbles are allowed except on this channel
4759 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004760
Mady Mellorbe797962019-04-01 16:04:24 -07004761 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004762 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004763 // Give it a person
4764 Person person = new Person.Builder()
4765 .setName("bubblebot")
4766 .build();
4767 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004768 Notification.Builder nb = new Notification.Builder(mContext,
4769 mTestNotificationChannel.getId())
4770 .setContentTitle("foo")
4771 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004772 .setStyle(new Notification.MessagingStyle(person)
4773 .setConversationTitle("Bubble Chat")
4774 .addMessage("Hello?",
4775 SystemClock.currentThreadTimeMillis() - 300000, person)
4776 .addMessage("Is it me you're looking for?",
4777 SystemClock.currentThreadTimeMillis(), person)
4778 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004779 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4780
4781 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4782 nb.build(), new UserHandle(mUid), null, 0);
4783 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4784
4785 // Post the notification
4786 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4787 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4788 waitForIdle();
4789
4790 // channel not allowed, no bubble
4791 assertFalse(mService.getNotificationRecord(
4792 sbn.getKey()).getNotification().isBubbleNotification());
4793 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004794
Mady Mellor49b1bf12019-03-29 12:00:02 -07004795 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004796 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004797 // Bubbles are not allowed!
4798 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004799
4800 // Give it bubble metadata
4801 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4802 // Give it a person
4803 Person person = new Person.Builder()
4804 .setName("bubblebot")
4805 .build();
4806 // Make it a phone call
4807 Notification.Builder nb = new Notification.Builder(mContext,
4808 mTestNotificationChannel.getId())
4809 .setCategory(CATEGORY_CALL)
4810 .addPerson(person)
4811 .setContentTitle("foo")
4812 .setBubbleMetadata(data)
4813 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4814
4815 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4816 nb.build(), new UserHandle(mUid), null, 0);
4817 // Make sure it has foreground service
4818 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4819 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4820
4821 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4822 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4823 waitForIdle();
4824
4825 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
4826 assertFalse(mService.getNotificationRecord(
4827 sbn.getKey()).getNotification().isBubbleNotification());
4828 }
4829
4830 @Test
4831 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004832 // Bubbles are allowed, but not on channel.
4833 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004834
4835 // Give it bubble metadata
4836 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4837 // Give it a person
4838 Person person = new Person.Builder()
4839 .setName("bubblebot")
4840 .build();
4841 // Make it a phone call
4842 Notification.Builder nb = new Notification.Builder(mContext,
4843 mTestNotificationChannel.getId())
4844 .setCategory(CATEGORY_CALL)
4845 .addPerson(person)
4846 .setContentTitle("foo")
4847 .setBubbleMetadata(data)
4848 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4849
4850 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4851 nb.build(), new UserHandle(mUid), null, 0);
4852 // Make sure it has foreground service
4853 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4854 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4855
4856 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4857 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4858 waitForIdle();
4859
4860 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
4861 assertFalse(mService.getNotificationRecord(
4862 sbn.getKey()).getNotification().isBubbleNotification());
4863 }
4864
4865 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07004866 public void testCancelAllNotifications_cancelsBubble() throws Exception {
4867 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4868 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
4869 mService.addNotification(nr);
4870
4871 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
4872 waitForIdle();
4873
4874 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4875 assertEquals(0, notifs.length);
4876 assertEquals(0, mService.getNotificationRecordCount());
4877 }
4878
4879 @Test
4880 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
4881 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4882 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4883
4884 // Post the notification
4885 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4886 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
4887 waitForIdle();
4888
4889 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4890 assertEquals(1, notifs.length);
4891 assertEquals(1, mService.getNotificationRecordCount());
4892
4893 mBinderService.cancelNotificationWithTag(PKG, null, nrBubble.sbn.getId(),
4894 nrBubble.sbn.getUserId());
4895 waitForIdle();
4896
4897 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4898 assertEquals(0, notifs2.length);
4899 assertEquals(0, mService.getNotificationRecordCount());
4900 }
4901
4902 @Test
4903 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
4904 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4905 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4906 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4907
4908 mService.addNotification(nrNormal);
4909 mService.addNotification(nrBubble);
4910
4911 mService.getBinderService().cancelNotificationsFromListener(null, null);
4912 waitForIdle();
4913
4914 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4915 assertEquals(1, notifs.length);
4916 assertEquals(1, mService.getNotificationRecordCount());
4917 }
4918
4919 @Test
4920 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
4921 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4922 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4923 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4924
4925 mService.addNotification(nrNormal);
4926 mService.addNotification(nrBubble);
4927
4928 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
4929 mService.getBinderService().cancelNotificationsFromListener(null, keys);
4930 waitForIdle();
4931
4932 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4933 assertEquals(1, notifs.length);
4934 assertEquals(1, mService.getNotificationRecordCount());
4935 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004936
Julia Reynolds4214da92019-04-10 15:04:06 -04004937 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04004938 public void testGetAllowedAssistantAdjustments() throws Exception {
4939 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004940 assertNotNull(capabilities);
4941
4942 for (int i = capabilities.size() - 1; i >= 0; i--) {
4943 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04004944 mBinderService.disallowAssistantAdjustment(capability);
4945 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
4946 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004947 assertNotNull(currentCapabilities);
4948 assertFalse(currentCapabilities.contains(capability));
4949 }
4950 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004951
Julia Reynolds4214da92019-04-10 15:04:06 -04004952 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004953 public void testAdjustRestrictedKey() throws Exception {
4954 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04004955 mService.addNotification(r);
4956 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004957
4958 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
4959 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
4960
4961 Bundle signals = new Bundle();
4962 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
4963 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
4964 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
4965 "", r.getUser().getIdentifier());
4966
4967 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
4968 r.applyAdjustments();
4969
4970 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
4971 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
4972 }
Julia Reynolds657d1642019-03-27 12:15:57 -04004973
Julia Reynolds4214da92019-04-10 15:04:06 -04004974 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004975 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04004976 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
4977 .thenReturn(true);
4978 mService.setZenHelper(mock(ZenModeHelper.class));
4979 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004980 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
4981 boolean isEnabled = true;
4982 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4983 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4984
4985 try {
4986 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04004987 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004988 } catch (IllegalArgumentException e) {
4989 // yay
4990 }
4991
4992 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4993 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
4994 mBinderService.addAutomaticZenRule(rule);
4995
4996 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4997 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4998 mBinderService.addAutomaticZenRule(rule);
4999 }
5000
Julia Reynolds4214da92019-04-10 15:04:06 -04005001 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005002 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5003 try {
5004 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5005 mUid + UserHandle.PER_USER_RANGE);
5006 fail("Cannot call cross user without permission");
5007 } catch (SecurityException e) {
5008 // pass
5009 }
5010
5011 // cross user, with permission, no problem
5012 TestablePermissions perms = mContext.getTestablePermissions();
5013 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5014 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5015 mUid + UserHandle.PER_USER_RANGE);
5016 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005017
Julia Reynolds4214da92019-04-10 15:04:06 -04005018 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005019 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5020 try {
5021 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5022 mUid + UserHandle.PER_USER_RANGE);
5023 fail("Cannot call cross user without permission");
5024 } catch (SecurityException e) {
5025 // pass
5026 }
5027
5028 // cross user, with permission, no problem
5029 TestablePermissions perms = mContext.getTestablePermissions();
5030 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5031 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5032 mUid + UserHandle.PER_USER_RANGE);
5033 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005034
5035 @Test
5036 public void testNotificationBubbleChanged_false() throws Exception {
5037 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005038 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005039
5040 // Notif with bubble metadata but not our other misc requirements
5041 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5042 null /* tvExtender */, true /* isBubble */);
5043
5044 // Say we're foreground
5045 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5046 IMPORTANCE_FOREGROUND);
5047
5048 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5049 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5050 waitForIdle();
5051
Mady Mellor66efd5e2019-05-15 13:38:11 -07005052 // Reset as this is called when the notif is first sent
5053 reset(mListeners);
5054
Mady Mellora54e9fa2019-04-18 13:26:18 -07005055 // First we were a bubble
5056 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5057 assertEquals(1, notifsBefore.length);
5058 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5059
5060 // Notify we're not a bubble
5061 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5062 waitForIdle();
5063
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005064 // Make sure we are not a bubble
5065 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5066 assertEquals(1, notifsAfter.length);
5067 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005068 }
5069
5070 @Test
5071 public void testNotificationBubbleChanged_true() throws Exception {
5072 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005073 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005074
5075 // Plain notification that has bubble metadata
5076 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5077 null /* tvExtender */, true /* isBubble */);
5078 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5079 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5080 waitForIdle();
5081
5082 // Would be a normal notification because wouldn't have met requirements to bubble
5083 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5084 assertEquals(1, notifsBefore.length);
5085 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5086
5087 // Make the package foreground so that we're allowed to be a bubble
5088 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5089 IMPORTANCE_FOREGROUND);
5090
Mady Mellor66efd5e2019-05-15 13:38:11 -07005091 // Reset as this is called when the notif is first sent
5092 reset(mListeners);
5093
Mady Mellora54e9fa2019-04-18 13:26:18 -07005094 // Notify we are now a bubble
5095 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5096 waitForIdle();
5097
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005098 // Make sure we are a bubble
5099 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5100 assertEquals(1, notifsAfter.length);
5101 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005102 }
5103
5104 @Test
5105 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5106 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005107 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005108
5109 // Notif that is not a bubble
5110 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5111 null /* tvExtender */, true /* isBubble */);
5112 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5113 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5114 waitForIdle();
5115
Mady Mellor66efd5e2019-05-15 13:38:11 -07005116 // Reset as this is called when the notif is first sent
5117 reset(mListeners);
5118
Mady Mellora54e9fa2019-04-18 13:26:18 -07005119 // Would be a normal notification because wouldn't have met requirements to bubble
5120 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5121 assertEquals(1, notifsBefore.length);
5122 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5123
5124 // Notify we are now a bubble
5125 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5126 waitForIdle();
5127
5128 // We still wouldn't be a bubble because the notification didn't meet requirements
5129 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5130 assertEquals(1, notifsAfter.length);
5131 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5132 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005133
5134 @Test
5135 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5136 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005137 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005138
5139 // Plain notification that has bubble metadata
5140 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5141 null /* tvExtender */, true /* isBubble */);
5142 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5143 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5144 waitForIdle();
5145
5146 // Would be a normal notification because wouldn't have met requirements to bubble
5147 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5148 assertEquals(1, notifsBefore.length);
5149 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5150
5151 // Make the package foreground so that we're allowed to be a bubble
5152 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5153 IMPORTANCE_FOREGROUND);
5154
5155 // And we are low ram
5156 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5157
5158 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5159 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5160 assertEquals(1, notifsAfter.length);
5161 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005162 }
Mady Mellora7731962019-06-17 17:57:02 -07005163
5164 @Test
5165 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
5166 throws Exception {
5167 // Bubbles are allowed!
5168 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5169
5170 // Give it bubble metadata
5171 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5172 .setSuppressNotification(true)
5173 .setAutoExpandBubble(true).build();
5174 // Give it a person
5175 Person person = new Person.Builder()
5176 .setName("bubblebot")
5177 .build();
5178 // It needs remote input to be bubble-able
5179 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5180 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5181 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5182 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5183 inputIntent).addRemoteInput(remoteInput)
5184 .build();
5185 // Make it messaging style
5186 Notification.Builder nb = new Notification.Builder(mContext,
5187 mTestNotificationChannel.getId())
5188 .setContentTitle("foo")
5189 .setBubbleMetadata(data)
5190 .setStyle(new Notification.MessagingStyle(person)
5191 .setConversationTitle("Bubble Chat")
5192 .addMessage("Hello?",
5193 SystemClock.currentThreadTimeMillis() - 300000, person)
5194 .addMessage("Is it me you're looking for?",
5195 SystemClock.currentThreadTimeMillis(), person)
5196 )
5197 .setActions(replyAction)
5198 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5199
5200 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5201 nb.build(), new UserHandle(mUid), null, 0);
5202 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5203
5204 // Ensure we're not foreground
5205 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5206 IMPORTANCE_VISIBLE);
5207
5208 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5209 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5210 waitForIdle();
5211
5212 // yes allowed, yes messaging, yes bubble
5213 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5214 assertTrue(notif.isBubbleNotification());
5215
5216 // Our flags should have failed since we're not foreground
5217 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
5218 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
5219 }
5220
5221 @Test
5222 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
5223 throws RemoteException {
5224 // Bubbles are allowed!
5225 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5226
5227 // Give it bubble metadata
5228 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5229 .setSuppressNotification(true)
5230 .setAutoExpandBubble(true).build();
5231 // Give it a person
5232 Person person = new Person.Builder()
5233 .setName("bubblebot")
5234 .build();
5235 // It needs remote input to be bubble-able
5236 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5237 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5238 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5239 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5240 inputIntent).addRemoteInput(remoteInput)
5241 .build();
5242 // Make it messaging style
5243 Notification.Builder nb = new Notification.Builder(mContext,
5244 mTestNotificationChannel.getId())
5245 .setContentTitle("foo")
5246 .setBubbleMetadata(data)
5247 .setStyle(new Notification.MessagingStyle(person)
5248 .setConversationTitle("Bubble Chat")
5249 .addMessage("Hello?",
5250 SystemClock.currentThreadTimeMillis() - 300000, person)
5251 .addMessage("Is it me you're looking for?",
5252 SystemClock.currentThreadTimeMillis(), person)
5253 )
5254 .setActions(replyAction)
5255 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5256
5257 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5258 nb.build(), new UserHandle(mUid), null, 0);
5259 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5260
5261 // Ensure we are in the foreground
5262 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5263 IMPORTANCE_FOREGROUND);
5264
5265 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5266 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5267 waitForIdle();
5268
5269 // yes allowed, yes messaging, yes bubble
5270 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5271 assertTrue(notif.isBubbleNotification());
5272
5273 // Our flags should have failed since we are foreground
5274 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
5275 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
5276 }
Mady Mellor22f2f072019-04-18 13:26:18 -07005277
5278 @Test
5279 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
5280 throws Exception {
5281 // Bubbles are allowed!
5282 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5283
5284 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5285 true /* summaryAutoCancel */);
5286
5287 // Dismiss summary
5288 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5289 true);
5290 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(),
5291 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(),
5292 NotificationStats.DISMISSAL_SHADE,
5293 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
5294 waitForIdle();
5295
5296 // The bubble should still exist
5297 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5298 assertEquals(1, notifsAfter.length);
5299 }
5300
5301 @Test
5302 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
5303 throws Exception {
5304 // Bubbles are allowed!
5305 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5306
5307 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5308 true /* summaryAutoCancel */);
5309
5310 // Click summary
5311 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5312 true);
5313 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
5314 nrSummary.getKey(), nv);
5315 waitForIdle();
5316
5317 // The bubble should still exist
5318 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5319 assertEquals(1, notifsAfter.length);
5320 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005321}