blob: 389b68a7d4b7988d545fa2a812175bd1a23ea5b3 [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
1020 public void testUserInitiatedClearAll_noLeak() throws Exception {
1021 final NotificationRecord n = generateNotificationRecord(
1022 mTestNotificationChannel, 1, "group", true);
1023
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001024 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001025 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
1026 waitForIdle();
1027
Julia Reynolds503ed942017-10-04 16:04:56 -04001028 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001029 n.getUserId());
1030 waitForIdle();
1031 StatusBarNotification[] notifs =
1032 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1033 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001034 assertEquals(0, mService.getNotificationRecordCount());
1035 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1036 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1037 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001038 }
1039
1040 @Test
1041 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1042 final NotificationRecord parent = generateNotificationRecord(
1043 mTestNotificationChannel, 1, "group1", true);
1044 final NotificationRecord child = generateNotificationRecord(
1045 mTestNotificationChannel, 2, "group1", false);
1046
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001047 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001048 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001049 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds080361e2017-07-13 11:23:12 -04001050 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1051 waitForIdle();
1052
1053 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1054 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001055 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001056 }
1057
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001058 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001059 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1060 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1061 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001062 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001063 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1064 }
1065 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1066 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001067
Julia Reynolds503ed942017-10-04 16:04:56 -04001068 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001069 }
1070
1071 @Test
1072 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1073 final NotificationRecord parent = generateNotificationRecord(
1074 mTestNotificationChannel, 1, "group1", true);
1075 final NotificationRecord parentAsChild = generateNotificationRecord(
1076 mTestNotificationChannel, 1, "group1", false);
1077 final NotificationRecord child = generateNotificationRecord(
1078 mTestNotificationChannel, 2, "group1", false);
1079
1080 // fully post parent notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001081 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001082 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1083 waitForIdle();
1084
1085 // enqueue the child several times
1086 for (int i = 0; i < 10; i++) {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001087 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001088 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1089 }
1090 // make the parent a child, which will cancel the child notification
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001091 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds0839c022017-06-15 15:24:01 -04001092 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1093 parentAsChild.sbn.getUserId());
1094 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001095
Julia Reynolds503ed942017-10-04 16:04:56 -04001096 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001097 }
1098
1099 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001100 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1101 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001102 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001103 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001104 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001105 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001106 waitForIdle();
1107 StatusBarNotification[] notifs =
1108 mBinderService.getActiveNotifications(sbn.getPackageName());
1109 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001110 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001111 }
1112
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001113 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001114 public void testCancelAllNotifications_IgnoreOtherPackages() 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 Pitsch331a64d2017-01-17 14:00:47 -05001119 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1120 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_NullPkgRemovesAll() throws Exception {
1129 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001130 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001131 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001132 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1133 waitForIdle();
1134 StatusBarNotification[] notifs =
1135 mBinderService.getActiveNotifications(sbn.getPackageName());
1136 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001137 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001138 }
1139
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001140 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001141 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1142 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001143 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001144 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001145 // Null pkg is how we signal a user switch.
1146 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1147 waitForIdle();
1148 StatusBarNotification[] notifs =
1149 mBinderService.getActiveNotifications(sbn.getPackageName());
1150 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001151 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001152 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001153
1154 @Test
Beverly40239d92017-07-07 10:20:41 -04001155 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1156 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1157 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001158 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Beverly40239d92017-07-07 10:20:41 -04001159 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1160 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1161 waitForIdle();
1162 StatusBarNotification[] notifs =
1163 mBinderService.getActiveNotifications(sbn.getPackageName());
1164 assertEquals(0, notifs.length);
1165 }
1166
1167 @Test
1168 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1169 final NotificationRecord notif = generateNotificationRecord(
1170 mTestNotificationChannel, 1, "group", true);
1171 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001172 mService.addNotification(notif);
1173 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001174 notif.getUserId(), 0, null);
1175 waitForIdle();
1176 StatusBarNotification[] notifs =
1177 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1178 assertEquals(0, notifs.length);
1179 }
1180
1181 @Test
1182 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() 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);
Beverly40239d92017-07-07 10:20:41 -04001187
Julia Reynolds503ed942017-10-04 16:04:56 -04001188 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001189 notif.getUserId());
1190 waitForIdle();
1191 StatusBarNotification[] notifs =
1192 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1193 assertEquals(1, notifs.length);
1194 }
1195
1196 @Test
1197 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1198 final NotificationRecord parent = generateNotificationRecord(
1199 mTestNotificationChannel, 1, "group", true);
1200 final NotificationRecord child = generateNotificationRecord(
1201 mTestNotificationChannel, 2, "group", false);
1202 final NotificationRecord child2 = generateNotificationRecord(
1203 mTestNotificationChannel, 3, "group", false);
1204 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1205 final NotificationRecord newGroup = generateNotificationRecord(
1206 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001207 mService.addNotification(parent);
1208 mService.addNotification(child);
1209 mService.addNotification(child2);
1210 mService.addNotification(newGroup);
1211 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001212 waitForIdle();
1213 StatusBarNotification[] notifs =
1214 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1215 assertEquals(1, notifs.length);
1216 }
1217
1218 @Test
1219 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1220 final NotificationRecord parent = generateNotificationRecord(
1221 mTestNotificationChannel, 1, "group", true);
1222 final NotificationRecord child = generateNotificationRecord(
1223 mTestNotificationChannel, 2, "group", false);
1224 final NotificationRecord child2 = generateNotificationRecord(
1225 mTestNotificationChannel, 3, "group", false);
1226 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1227 final NotificationRecord newGroup = generateNotificationRecord(
1228 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001229 mService.addNotification(parent);
1230 mService.addNotification(child);
1231 mService.addNotification(child2);
1232 mService.addNotification(newGroup);
1233 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001234 parent.getUserId());
1235 waitForIdle();
1236 StatusBarNotification[] notifs =
1237 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1238 assertEquals(1, notifs.length);
1239 }
1240
1241 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001242 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
1243 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001244 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001245 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001246 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001247 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1248 sbn.getUserId());
1249 waitForIdle();
1250 StatusBarNotification[] notifs =
1251 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001252 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001253 }
1254
1255 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001256 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1257 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1258 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001259 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001260 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001261 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1262 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001263 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001264 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1265 mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
1266 waitForIdle();
1267 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001268 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001269 }
1270
1271 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001272 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1273 throws Exception {
1274 final NotificationRecord parent = generateNotificationRecord(
1275 mTestNotificationChannel, 1, "group", true);
1276 final NotificationRecord child = generateNotificationRecord(
1277 mTestNotificationChannel, 2, "group", false);
1278 final NotificationRecord child2 = generateNotificationRecord(
1279 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001280 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001281 final NotificationRecord newGroup = generateNotificationRecord(
1282 mTestNotificationChannel, 4, "group2", false);
1283 mService.addNotification(parent);
1284 mService.addNotification(child);
1285 mService.addNotification(child2);
1286 mService.addNotification(newGroup);
1287 mService.getBinderService().cancelNotificationsFromListener(null, null);
1288 waitForIdle();
1289 StatusBarNotification[] notifs =
1290 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1291 assertEquals(0, notifs.length);
1292 }
1293
1294 @Test
1295 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1296 throws Exception {
1297 final NotificationRecord parent = generateNotificationRecord(
1298 mTestNotificationChannel, 1, "group", true);
1299 final NotificationRecord child = generateNotificationRecord(
1300 mTestNotificationChannel, 2, "group", false);
1301 final NotificationRecord child2 = generateNotificationRecord(
1302 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001303 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001304 final NotificationRecord newGroup = generateNotificationRecord(
1305 mTestNotificationChannel, 4, "group2", false);
1306 mService.addNotification(parent);
1307 mService.addNotification(child);
1308 mService.addNotification(child2);
1309 mService.addNotification(newGroup);
1310 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1311 child2.sbn.getKey(), newGroup.sbn.getKey()};
1312 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1313 waitForIdle();
1314 StatusBarNotification[] notifs =
1315 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1316 assertEquals(1, notifs.length);
1317 }
1318
1319 @Test
1320 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1321 final NotificationRecord parent = generateNotificationRecord(
1322 mTestNotificationChannel, 1, "group", true);
1323 final NotificationRecord child = generateNotificationRecord(
1324 mTestNotificationChannel, 2, "group", false);
1325 final NotificationRecord child2 = generateNotificationRecord(
1326 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001327 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001328 final NotificationRecord newGroup = generateNotificationRecord(
1329 mTestNotificationChannel, 4, "group2", false);
1330 mService.addNotification(parent);
1331 mService.addNotification(child);
1332 mService.addNotification(child2);
1333 mService.addNotification(newGroup);
1334 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1335 parent.getUserId());
1336 waitForIdle();
1337 StatusBarNotification[] notifs =
1338 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1339 assertEquals(0, notifs.length);
1340 }
1341
1342 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001343 public void testFindGroupNotificationsLocked() throws Exception {
1344 // make sure the same notification can be found in both lists and returned
1345 final NotificationRecord group1 = generateNotificationRecord(
1346 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001347 mService.addEnqueuedNotification(group1);
1348 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001349
1350 // should not be returned
1351 final NotificationRecord group2 = generateNotificationRecord(
1352 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001353 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001354 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1355 waitForIdle();
1356
1357 // should not be returned
1358 final NotificationRecord nonGroup = generateNotificationRecord(
1359 mTestNotificationChannel, 3, null, false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001360 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001361 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1362 waitForIdle();
1363
1364 // same group, child, should be returned
1365 final NotificationRecord group1Child = generateNotificationRecord(
1366 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001367 mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001368 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1369 waitForIdle();
1370
1371 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001372 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001373 group1.sbn.getUserId());
1374 assertEquals(3, inGroup1.size());
1375 for (NotificationRecord record : inGroup1) {
1376 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1377 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1378 }
1379 }
1380
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001381 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001382 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1383 final NotificationRecord notif = generateNotificationRecord(
1384 mTestNotificationChannel, 1, "group", true);
1385 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1386 mService.addNotification(notif);
1387 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1388 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1389 waitForIdle();
1390 StatusBarNotification[] notifs =
1391 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1392 assertEquals(0, notifs.length);
1393 }
1394
1395 @Test
1396 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1397 throws Exception {
1398 final NotificationRecord parent = generateNotificationRecord(
1399 mTestNotificationChannel, 1, "group", true);
1400 final NotificationRecord child = generateNotificationRecord(
1401 mTestNotificationChannel, 2, "group", false);
1402 final NotificationRecord child2 = generateNotificationRecord(
1403 mTestNotificationChannel, 3, "group", false);
1404 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1405 final NotificationRecord newGroup = generateNotificationRecord(
1406 mTestNotificationChannel, 4, "group2", false);
1407 mService.addNotification(parent);
1408 mService.addNotification(child);
1409 mService.addNotification(child2);
1410 mService.addNotification(newGroup);
1411 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1412 child2.sbn.getKey(), newGroup.sbn.getKey()};
1413 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1414 waitForIdle();
1415 StatusBarNotification[] notifs =
1416 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1417 assertEquals(0, notifs.length);
1418 }
1419
1420 @Test
1421 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1422 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1423 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001424 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001425 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1426 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1427 waitForIdle();
1428 StatusBarNotification[] notifs =
1429 mBinderService.getActiveNotifications(sbn.getPackageName());
1430 assertEquals(0, notifs.length);
1431 }
1432
1433 @Test
1434 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1435 final NotificationRecord notif = generateNotificationRecord(
1436 mTestNotificationChannel, 1, "group", true);
1437 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1438 mService.addNotification(notif);
1439 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1440 notif.getUserId(), 0, null);
1441 waitForIdle();
1442 StatusBarNotification[] notifs =
1443 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1444 assertEquals(0, notifs.length);
1445 }
1446
1447 @Test
1448 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() 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
1454 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1455 notif.getUserId());
1456 waitForIdle();
1457 StatusBarNotification[] notifs =
1458 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1459 assertEquals(1, notifs.length);
1460 }
1461
1462 @Test
1463 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1464 final NotificationRecord parent = generateNotificationRecord(
1465 mTestNotificationChannel, 1, "group", true);
1466 final NotificationRecord child = generateNotificationRecord(
1467 mTestNotificationChannel, 2, "group", false);
1468 final NotificationRecord child2 = generateNotificationRecord(
1469 mTestNotificationChannel, 3, "group", false);
1470 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1471 final NotificationRecord newGroup = generateNotificationRecord(
1472 mTestNotificationChannel, 4, "group2", false);
1473 mService.addNotification(parent);
1474 mService.addNotification(child);
1475 mService.addNotification(child2);
1476 mService.addNotification(newGroup);
1477 mService.getBinderService().cancelNotificationsFromListener(null, null);
1478 waitForIdle();
1479 StatusBarNotification[] notifs =
1480 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1481 assertEquals(1, notifs.length);
1482 }
1483
1484 @Test
1485 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1486 throws Exception {
1487 final NotificationRecord parent = generateNotificationRecord(
1488 mTestNotificationChannel, 1, "group", true);
1489 final NotificationRecord child = generateNotificationRecord(
1490 mTestNotificationChannel, 2, "group", false);
1491 final NotificationRecord child2 = generateNotificationRecord(
1492 mTestNotificationChannel, 3, "group", false);
1493 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1494 final NotificationRecord newGroup = generateNotificationRecord(
1495 mTestNotificationChannel, 4, "group2", false);
1496 mService.addNotification(parent);
1497 mService.addNotification(child);
1498 mService.addNotification(child2);
1499 mService.addNotification(newGroup);
1500 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1501 child2.sbn.getKey(), newGroup.sbn.getKey()};
1502 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1503 waitForIdle();
1504 StatusBarNotification[] notifs =
1505 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1506 assertEquals(0, notifs.length);
1507 }
1508
1509 @Test
1510 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1511 final NotificationRecord parent = generateNotificationRecord(
1512 mTestNotificationChannel, 1, "group", true);
1513 final NotificationRecord child = generateNotificationRecord(
1514 mTestNotificationChannel, 2, "group", false);
1515 final NotificationRecord child2 = generateNotificationRecord(
1516 mTestNotificationChannel, 3, "group", false);
1517 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1518 final NotificationRecord newGroup = generateNotificationRecord(
1519 mTestNotificationChannel, 4, "group2", false);
1520 mService.addNotification(parent);
1521 mService.addNotification(child);
1522 mService.addNotification(child2);
1523 mService.addNotification(newGroup);
1524 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1525 parent.getUserId());
1526 waitForIdle();
1527 StatusBarNotification[] notifs =
1528 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1529 assertEquals(1, notifs.length);
1530 }
1531
1532 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001533 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001534 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001535 mService.setPreferencesHelper(mPreferencesHelper);
1536 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001537 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001538 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001539
Julia Reynoldsbad42972017-04-25 13:52:49 -04001540 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001541 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001542 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001543 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001544 anyString(), anyInt(), eq("foo"), anyBoolean());
1545 }
1546
1547 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001548 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001549 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001550 mService.setPreferencesHelper(mPreferencesHelper);
1551 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001552 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001553 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001554
Julia Reynoldsbad42972017-04-25 13:52:49 -04001555 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001556 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001557 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001558 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001559 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001560 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001561
1562 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001563 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001564 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001565
Julia Reynolds4f5020d2019-06-03 12:48:49 -04001566 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001567 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1568 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1569
1570 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1571 captor.getValue().getAction());
1572 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynolds4f5020d2019-06-03 12:48:49 -04001573 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1574 }
1575
1576 @Test
1577 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1578 mService.setPreferencesHelper(mPreferencesHelper);
1579
1580 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1581 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001582 }
1583
1584 @Test
1585 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001586 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001587
1588 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1589 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1590 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1591
1592 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1593 captor.getValue().getAction());
1594 assertEquals(PKG, captor.getValue().getPackage());
1595 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1596 }
1597
1598 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001599 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001600 mService.setPreferencesHelper(mPreferencesHelper);
1601 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001602 eq(mTestNotificationChannel.getId()), anyBoolean()))
1603 .thenReturn(mTestNotificationChannel);
1604
1605 NotificationChannel updatedChannel =
1606 new NotificationChannel(mTestNotificationChannel.getId(),
1607 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1608
1609 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1610 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1611 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1612
1613 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1614 captor.getValue().getAction());
1615 assertEquals(PKG, captor.getValue().getPackage());
1616 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001617 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001618 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1619 }
1620
1621 @Test
1622 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1623 NotificationChannel existingChannel =
1624 new NotificationChannel(mTestNotificationChannel.getId(),
1625 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001626 mService.setPreferencesHelper(mPreferencesHelper);
1627 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001628 eq(mTestNotificationChannel.getId()), anyBoolean()))
1629 .thenReturn(existingChannel);
1630
1631 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1632 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1633 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1634
1635 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1636 captor.getValue().getAction());
1637 assertEquals(PKG, captor.getValue().getPackage());
1638 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001639 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001640 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1641 }
1642
1643 @Test
1644 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1645 NotificationChannel existingChannel =
1646 new NotificationChannel(mTestNotificationChannel.getId(),
1647 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001648 mService.setPreferencesHelper(mPreferencesHelper);
1649 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001650 eq(mTestNotificationChannel.getId()), anyBoolean()))
1651 .thenReturn(existingChannel);
1652
1653 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1654 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1655 }
1656
1657 @Test
1658 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1659 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001660 mService.setPreferencesHelper(mPreferencesHelper);
1661 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001662 .thenReturn(existing);
1663
1664 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1665 updated.setBlocked(true);
1666
1667 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1668 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1669 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1670
1671 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1672 captor.getValue().getAction());
1673 assertEquals(PKG, captor.getValue().getPackage());
1674 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001675 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001676 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1677 }
1678
1679 @Test
1680 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1681 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1682 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001683 mService.setPreferencesHelper(mPreferencesHelper);
1684 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001685 .thenReturn(existing);
1686
1687 mBinderService.updateNotificationChannelGroupForPackage(
1688 PKG, 0, new NotificationChannelGroup("id", "name"));
1689 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1690 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1691
1692 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1693 captor.getValue().getAction());
1694 assertEquals(PKG, captor.getValue().getPackage());
1695 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001696 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001697 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1698 }
1699
1700 @Test
1701 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1702 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001703 mService.setPreferencesHelper(mPreferencesHelper);
1704 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001705 .thenReturn(existing);
1706
1707 mBinderService.updateNotificationChannelGroupForPackage(
1708 PKG, 0, new NotificationChannelGroup("id", "new name"));
1709 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1710 }
1711
1712 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001713 public void testCreateChannelNotifyListener() throws Exception {
1714 List<String> associations = new ArrayList<>();
1715 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001716 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001717 mService.setPreferencesHelper(mPreferencesHelper);
1718 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001719 eq(mTestNotificationChannel.getId()), anyBoolean()))
1720 .thenReturn(mTestNotificationChannel);
1721 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001722 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001723 eq(channel2.getId()), anyBoolean()))
1724 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001725 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1726 eq(channel2), anyBoolean(), anyBoolean()))
1727 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001728
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001729 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001730 mBinderService.createNotificationChannels(PKG,
1731 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001732 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001733 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001734 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001735 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001736 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001737 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1738 }
1739
1740 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001741 public void testCreateChannelGroupNotifyListener() throws Exception {
1742 List<String> associations = new ArrayList<>();
1743 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001744 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001745 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001746 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1747 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1748
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001749 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001750 mBinderService.createNotificationChannelGroups(PKG,
1751 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001752 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001753 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001754 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001755 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001756 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001757 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1758 }
1759
1760 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001761 public void testUpdateChannelNotifyListener() throws Exception {
1762 List<String> associations = new ArrayList<>();
1763 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001764 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001765 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001766 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001767 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001768 eq(mTestNotificationChannel.getId()), anyBoolean()))
1769 .thenReturn(mTestNotificationChannel);
1770
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001771 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001772 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001773 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001774 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001775 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1776 }
1777
1778 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001779 public void testDeleteChannelNotifyListener() throws Exception {
1780 List<String> associations = new ArrayList<>();
1781 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001782 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001783 mService.setPreferencesHelper(mPreferencesHelper);
1784 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001785 eq(mTestNotificationChannel.getId()), anyBoolean()))
1786 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001787 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001788 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001789 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001790 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001791 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1792 }
1793
1794 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001795 public void testDeleteChannelGroupNotifyListener() throws Exception {
1796 List<String> associations = new ArrayList<>();
1797 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001798 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001799 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001800 mService.setPreferencesHelper(mPreferencesHelper);
1801 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001802 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001803 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001804 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001805 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001806 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001807 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1808 }
1809
1810 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001811 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001812 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001813 List<String> associations = new ArrayList<>();
1814 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001815 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001816 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001817 eq(mTestNotificationChannel.getId()), anyBoolean()))
1818 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001819
1820 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001821 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001822
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001823 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001824 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001825
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001826 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001827 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001828 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1829 }
1830
1831 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001832 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001833 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001834 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001835 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001836
1837 try {
1838 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001839 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001840 fail("listeners that don't have a companion device shouldn't be able to call this");
1841 } catch (SecurityException e) {
1842 // pass
1843 }
1844
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001845 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001846 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001847
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001848 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001849 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1850 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1851 }
1852
1853 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001854 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001855 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001856 List<String> associations = new ArrayList<>();
1857 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001858 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001859 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04001860 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001861 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001862 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001863
1864 try {
1865 mBinderService.updateNotificationChannelFromPrivilegedListener(
1866 null, PKG, UserHandle.ALL, mTestNotificationChannel);
1867 fail("incorrectly allowed a change to a user listener cannot see");
1868 } catch (SecurityException e) {
1869 // pass
1870 }
1871
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001872 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001873 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001874
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001875 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001876 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001877 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1878 }
1879
1880 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001881 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001882 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001883 List<String> associations = new ArrayList<>();
1884 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001885 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001886
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001887 mBinderService.getNotificationChannelsFromPrivilegedListener(
1888 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001889
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001890 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001891 anyString(), anyInt(), anyBoolean());
1892 }
1893
1894 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001895 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() 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<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001898 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001899
1900 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001901 mBinderService.getNotificationChannelsFromPrivilegedListener(
1902 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001903 fail("listeners that don't have a companion device shouldn't be able to call this");
1904 } catch (SecurityException e) {
1905 // pass
1906 }
1907
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001908 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001909 anyString(), anyInt(), anyBoolean());
1910 }
1911
1912 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001913 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
1914 throws Exception {
1915 mService.setPreferencesHelper(mPreferencesHelper);
1916 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1917 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
1918
1919 mBinderService.getNotificationChannelsFromPrivilegedListener(
1920 null, PKG, Process.myUserHandle());
1921
1922 verify(mPreferencesHelper, times(1)).getNotificationChannels(
1923 anyString(), anyInt(), anyBoolean());
1924 }
1925
1926 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04001927 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
1928 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04001929 mService.setPreferencesHelper(mPreferencesHelper);
1930 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
1931 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
1932
1933 try {
1934 mBinderService.getNotificationChannelsFromPrivilegedListener(
1935 null, PKG, Process.myUserHandle());
1936 fail("listeners that don't have a companion device shouldn't be able to call this");
1937 } catch (SecurityException e) {
1938 // pass
1939 }
1940
1941 verify(mPreferencesHelper, never()).getNotificationChannels(
1942 anyString(), anyInt(), anyBoolean());
1943 }
1944
1945 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001946 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001947 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001948 List<String> associations = new ArrayList<>();
1949 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001950 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001951 mListener = mock(ManagedServices.ManagedServiceInfo.class);
1952 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001953 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001954
1955 try {
1956 mBinderService.getNotificationChannelsFromPrivilegedListener(
1957 null, PKG, Process.myUserHandle());
1958 fail("listener getting channels from a user they cannot see");
1959 } catch (SecurityException e) {
1960 // pass
1961 }
1962
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001963 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001964 anyString(), anyInt(), anyBoolean());
1965 }
1966
1967 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001968 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001969 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001970 List<String> associations = new ArrayList<>();
1971 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001972 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001973
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001974 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1975 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001976
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001977 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001978 }
1979
1980 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001981 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001982 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001983 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001984 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001985
1986 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001987 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
1988 null, PKG, Process.myUserHandle());
1989 fail("listeners that don't have a companion device shouldn't be able to call this");
1990 } catch (SecurityException e) {
1991 // pass
1992 }
1993
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001994 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001995 }
1996
1997 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001998 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001999 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002000 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002001 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002002 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2003 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002004 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002005 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002006 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2007 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002008 fail("listeners that don't have a companion device shouldn't be able to call this");
2009 } catch (SecurityException e) {
2010 // pass
2011 }
2012
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002013 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002014 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002015
2016 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002017 public void testHasCompanionDevice_failure() throws Exception {
2018 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2019 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002020 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002021 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002022
2023 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002024 public void testHasCompanionDevice_noService() {
2025 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04002026
Julia Reynolds503ed942017-10-04 16:04:56 -04002027 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002028 }
2029
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002030 @Test
2031 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2032 final NotificationRecord nonGrouped = generateNotificationRecord(
2033 mTestNotificationChannel, 1, null, false);
2034 final NotificationRecord grouped = generateNotificationRecord(
2035 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002036 mService.addNotification(grouped);
2037 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002038
2039 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002040 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002041 nonGrouped.getKey(), 100, null);
2042 snoozeNotificationRunnable.run();
2043
2044 // only snooze the one notification
2045 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002046 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002047 }
2048
2049 @Test
2050 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2051 final NotificationRecord parent = generateNotificationRecord(
2052 mTestNotificationChannel, 1, "group", true);
2053 final NotificationRecord child = generateNotificationRecord(
2054 mTestNotificationChannel, 2, "group", false);
2055 final NotificationRecord child2 = generateNotificationRecord(
2056 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002057 mService.addNotification(parent);
2058 mService.addNotification(child);
2059 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002060
2061 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002062 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002063 parent.getKey(), 100, null);
2064 snoozeNotificationRunnable.run();
2065
2066 // snooze parent and children
2067 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2068 }
2069
2070 @Test
2071 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2072 final NotificationRecord parent = generateNotificationRecord(
2073 mTestNotificationChannel, 1, "group", true);
2074 final NotificationRecord child = generateNotificationRecord(
2075 mTestNotificationChannel, 2, "group", false);
2076 final NotificationRecord child2 = generateNotificationRecord(
2077 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002078 mService.addNotification(parent);
2079 mService.addNotification(child);
2080 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002081
2082 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002083 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002084 child2.getKey(), 100, null);
2085 snoozeNotificationRunnable.run();
2086
2087 // only snooze the one child
2088 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2089 }
2090
2091 @Test
2092 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2093 final NotificationRecord parent = generateNotificationRecord(
2094 mTestNotificationChannel, 1, "group", true);
2095 assertTrue(parent.sbn.getNotification().isGroupSummary());
2096 final NotificationRecord child = generateNotificationRecord(
2097 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002098 mService.addNotification(parent);
2099 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002100
2101 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002102 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002103 child.getKey(), 100, null);
2104 snoozeNotificationRunnable.run();
2105
2106 // snooze child and summary
2107 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2108 }
2109
2110 @Test
2111 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2112 final NotificationRecord child = generateNotificationRecord(
2113 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002114 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002115
2116 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002117 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002118 child.getKey(), 100, null);
2119 snoozeNotificationRunnable.run();
2120
2121 // snooze child only
2122 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2123 }
2124
2125 @Test
2126 public void testPostGroupChild_unsnoozeParent() throws Exception {
2127 final NotificationRecord child = generateNotificationRecord(
2128 mTestNotificationChannel, 2, "group", false);
2129
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002130 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002131 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2132 waitForIdle();
2133
2134 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2135 anyString(), anyInt(), eq(child.getGroupKey()));
2136 }
2137
2138 @Test
2139 public void testPostNonGroup_noUnsnoozing() throws Exception {
2140 final NotificationRecord record = generateNotificationRecord(
2141 mTestNotificationChannel, 2, null, false);
2142
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002143 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002144 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2145 waitForIdle();
2146
2147 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2148 }
2149
2150 @Test
2151 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2152 final NotificationRecord parent = generateNotificationRecord(
2153 mTestNotificationChannel, 2, "group", true);
2154
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002155 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002156 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2157 waitForIdle();
2158
2159 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2160 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002161
2162 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002163 public void testSetListenerAccessForUser() throws Exception {
2164 UserHandle user = UserHandle.of(10);
2165 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002166 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2167
Julia Reynolds92febc32017-10-26 11:30:31 -04002168
2169 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2170 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2171 c.flattenToString(), user.getIdentifier(), true, true);
2172 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2173 c.flattenToString(), user.getIdentifier(), false, true);
2174 verify(mAssistants, never()).setPackageOrComponentEnabled(
2175 any(), anyInt(), anyBoolean(), anyBoolean());
2176 }
2177
2178 @Test
2179 public void testSetAssistantAccessForUser() throws Exception {
2180 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002181 List<UserInfo> uis = new ArrayList<>();
2182 UserInfo ui = new UserInfo();
2183 ui.id = 10;
2184 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002185 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002186 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2187
2188 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002189
2190 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2191 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2192 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002193 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002194 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2195 c.flattenToString(), user.getIdentifier(), false, true);
2196 verify(mListeners, never()).setPackageOrComponentEnabled(
2197 any(), anyInt(), anyBoolean(), anyBoolean());
2198 }
2199
2200 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002201 public void testGetAssistantAllowedForUser() throws Exception {
2202 UserHandle user = UserHandle.of(10);
2203 try {
2204 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2205 } catch (IllegalStateException e) {
2206 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2207 throw e;
2208 }
2209 }
2210 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2211 }
2212
2213 @Test
2214 public void testGetAssistantAllowed() throws Exception {
2215 try {
2216 mBinderService.getAllowedNotificationAssistant();
2217 } catch (IllegalStateException e) {
2218 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2219 throw e;
2220 }
2221 }
2222 verify(mAssistants, times(1)).getAllowedComponents(0);
2223 }
2224
2225 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002226 public void testSetDndAccessForUser() throws Exception {
2227 UserHandle user = UserHandle.of(10);
2228 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002229 mBinderService.setNotificationPolicyAccessGrantedForUser(
2230 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002231
2232 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2233 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2234 c.getPackageName(), user.getIdentifier(), true, true);
2235 verify(mAssistants, never()).setPackageOrComponentEnabled(
2236 any(), anyInt(), anyBoolean(), anyBoolean());
2237 verify(mListeners, never()).setPackageOrComponentEnabled(
2238 any(), anyInt(), anyBoolean(), anyBoolean());
2239 }
2240
2241 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002242 public void testSetListenerAccess() throws Exception {
2243 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002244 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002245
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002246 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002247 c.flattenToString(), 0, true, true);
2248 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2249 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002250 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002251 any(), anyInt(), anyBoolean(), anyBoolean());
2252 }
2253
2254 @Test
2255 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002256 List<UserInfo> uis = new ArrayList<>();
2257 UserInfo ui = new UserInfo();
2258 ui.id = 0;
2259 uis.add(ui);
2260 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002261 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002262
2263 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002264
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002265 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002266 c.flattenToString(), 0, true, true);
2267 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2268 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002269 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002270 any(), anyInt(), anyBoolean(), anyBoolean());
2271 }
2272
2273 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002274 public void testSetAssistantAccess_multiProfile() throws Exception {
2275 List<UserInfo> uis = new ArrayList<>();
2276 UserInfo ui = new UserInfo();
2277 ui.id = 0;
2278 uis.add(ui);
2279 UserInfo ui10 = new UserInfo();
2280 ui10.id = 10;
2281 uis.add(ui10);
2282 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2283 ComponentName c = ComponentName.unflattenFromString("package/Component");
2284
2285 mBinderService.setNotificationAssistantAccessGranted(c, true);
2286
2287 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2288 c.flattenToString(), 0, true, true);
2289 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2290 c.flattenToString(), 10, true, true);
2291 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2292 c.flattenToString(), 0, false, true);
2293 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2294 c.flattenToString(), 10, false, true);
2295 verify(mListeners, never()).setPackageOrComponentEnabled(
2296 any(), anyInt(), anyBoolean(), anyBoolean());
2297 }
2298
2299 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002300 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2301 ArrayList<ComponentName> componentList = new ArrayList<>();
2302 ComponentName c = ComponentName.unflattenFromString("package/Component");
2303 componentList.add(c);
2304 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002305 List<UserInfo> uis = new ArrayList<>();
2306 UserInfo ui = new UserInfo();
2307 ui.id = 0;
2308 uis.add(ui);
2309 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002310
Julia Reynolds4afe2642019-05-01 08:42:24 -04002311 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002312
2313 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2314 c.flattenToString(), 0, true, false);
2315 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2316 c.flattenToString(), 0, false, false);
2317 verify(mListeners, never()).setPackageOrComponentEnabled(
2318 any(), anyInt(), anyBoolean(), anyBoolean());
2319 }
2320
2321 @Test
2322 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002323 List<UserInfo> uis = new ArrayList<>();
2324 UserInfo ui = new UserInfo();
2325 ui.id = 10;
2326 uis.add(ui);
2327 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002328 ArrayList<ComponentName> componentList = new ArrayList<>();
2329 ComponentName c = ComponentName.unflattenFromString("package/Component");
2330 componentList.add(c);
2331 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002332 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002333
Julia Reynolds4afe2642019-05-01 08:42:24 -04002334 mBinderService.setNotificationAssistantAccessGrantedForUser(
2335 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002336
2337 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2338 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002339 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002340 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2341 c.flattenToString(), user.getIdentifier(), false, false);
2342 verify(mListeners, never()).setPackageOrComponentEnabled(
2343 any(), anyInt(), anyBoolean(), anyBoolean());
2344 }
2345
2346 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002347 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2348 throws Exception {
2349 List<UserInfo> uis = new ArrayList<>();
2350 UserInfo ui = new UserInfo();
2351 ui.id = 0;
2352 uis.add(ui);
2353 UserInfo ui10 = new UserInfo();
2354 ui10.id = 10;
2355 uis.add(ui10);
2356 UserHandle user = ui.getUserHandle();
2357 ArrayList<ComponentName> componentList = new ArrayList<>();
2358 ComponentName c = ComponentName.unflattenFromString("package/Component");
2359 componentList.add(c);
2360 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2361 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2362
2363 mBinderService.setNotificationAssistantAccessGrantedForUser(
2364 null, user.getIdentifier(), true);
2365
2366 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2367 c.flattenToString(), user.getIdentifier(), true, false);
2368 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2369 c.flattenToString(), ui10.id, true, false);
2370 verify(mAssistants).setUserSet(0, true);
2371 verify(mAssistants).setUserSet(10, true);
2372 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2373 c.flattenToString(), user.getIdentifier(), false, false);
2374 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2375 c.flattenToString(), ui10.id, false, false);
2376 verify(mListeners, never()).setPackageOrComponentEnabled(
2377 any(), anyInt(), anyBoolean(), anyBoolean());
2378 }
2379
2380 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002381 public void testSetDndAccess() throws Exception {
2382 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002383
2384 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002385
2386 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2387 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002388 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002389 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002390 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002391 any(), anyInt(), anyBoolean(), anyBoolean());
2392 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002393
2394 @Test
2395 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2396 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2397 ComponentName c = ComponentName.unflattenFromString("package/Component");
2398 mBinderService.setNotificationListenerAccessGranted(c, true);
2399
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002400 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002401 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002402 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002403 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002404 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002405 any(), anyInt(), anyBoolean(), anyBoolean());
2406 }
2407
2408 @Test
2409 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2410 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2411 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002412 List<UserInfo> uis = new ArrayList<>();
2413 UserInfo ui = new UserInfo();
2414 ui.id = 0;
2415 uis.add(ui);
2416 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2417
Julia Reynolds68263d12017-06-21 14:21:19 -04002418 mBinderService.setNotificationAssistantAccessGranted(c, true);
2419
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002420 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002421 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002422 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002423 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002424 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002425 any(), anyInt(), anyBoolean(), anyBoolean());
2426 }
2427
2428 @Test
2429 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2430 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2431 ComponentName c = ComponentName.unflattenFromString("package/Component");
2432 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), 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());
2438 verify(mAssistants, never()).setPackageOrComponentEnabled(
2439 any(), anyInt(), anyBoolean(), anyBoolean());
2440 }
2441
2442 @Test
2443 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2444 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2445 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2446 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002447
2448 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002449
2450 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2451 c.flattenToString(), 0, true, true);
2452 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002453 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002454 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002455 any(), anyInt(), anyBoolean(), anyBoolean());
2456 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002457
2458 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002459 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2460 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2461 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2462 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002463 List<UserInfo> uis = new ArrayList<>();
2464 UserInfo ui = new UserInfo();
2465 ui.id = 0;
2466 uis.add(ui);
2467 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2468
2469 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002470
2471 verify(mListeners, never()).setPackageOrComponentEnabled(
2472 anyString(), anyInt(), anyBoolean(), anyBoolean());
2473 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2474 c.flattenToString(), 0, false, true);
2475 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2476 c.flattenToString(), 0, true, true);
2477 }
2478
2479 @Test
2480 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2481 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2482 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2483 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002484
2485 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002486
2487 verify(mListeners, never()).setPackageOrComponentEnabled(
2488 anyString(), anyInt(), anyBoolean(), anyBoolean());
2489 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2490 c.getPackageName(), 0, true, true);
2491 verify(mAssistants, never()).setPackageOrComponentEnabled(
2492 any(), anyInt(), anyBoolean(), anyBoolean());
2493 }
2494
2495 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002496 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2497 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002498 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002499 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002500 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002501 runnable.run();
2502 waitForIdle();
2503
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002504 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002505 }
2506
2507 @Test
2508 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2509 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002510 NotificationRecord r =
2511 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002512 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002513
2514 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002515 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002516 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002517 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002518 runnable.run();
2519 waitForIdle();
2520
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002521 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002522 }
2523
2524 @Test
2525 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2526 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002527 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2528 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002529 mService.addNotification(r);
2530 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002531
2532 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002533 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002534 runnable.run();
2535 waitForIdle();
2536
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002537 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002538 }
Beverly40239d92017-07-07 10:20:41 -04002539
Julia Reynolds4db59552017-06-30 13:34:01 -04002540 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002541 public void testDontAutogroupIfCritical() throws Exception {
2542 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2543 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2544 mService.addEnqueuedNotification(r);
2545 NotificationManagerService.PostNotificationRunnable runnable =
2546 mService.new PostNotificationRunnable(r.getKey());
2547 runnable.run();
2548
2549 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2550 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2551 runnable = mService.new PostNotificationRunnable(r.getKey());
2552 mService.addEnqueuedNotification(r);
2553
2554 runnable.run();
2555 waitForIdle();
2556
2557 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2558 }
2559
2560 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002561 public void testNoFakeColorizedPermission() throws Exception {
2562 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2563 Notification.Builder nb = new Notification.Builder(mContext,
2564 mTestNotificationChannel.getId())
2565 .setContentTitle("foo")
2566 .setColorized(true)
2567 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2568 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002569 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
2570 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002571 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2572
2573 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
2574 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2575 waitForIdle();
2576
Julia Reynolds503ed942017-10-04 16:04:56 -04002577 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds4db59552017-06-30 13:34:01 -04002578 PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
2579
2580 assertFalse(posted.getNotification().isColorized());
2581 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002582
2583 @Test
2584 public void testGetNotificationCountLocked() throws Exception {
2585 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002586 NotificationRecord r =
2587 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002588 mService.addEnqueuedNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002589 }
2590 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002591 NotificationRecord r =
2592 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002593 mService.addNotification(r);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002594 }
2595
2596 // another package
2597 Notification n =
2598 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2599 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2600 .build();
2601
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002602 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2603 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002604 NotificationRecord otherPackage =
2605 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002606 mService.addEnqueuedNotification(otherPackage);
2607 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002608
2609 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002610 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002611 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002612 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002613 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002614 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002615 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002616 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002617
2618 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002619 assertEquals(39,
Julia Reynolds503ed942017-10-04 16:04:56 -04002620 mService.getNotificationCountLocked(PKG, userId, 0, "tag"));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002621 }
2622
2623 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002624 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002625 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002626 mService.setRankingHandler(rh);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002627
2628 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002629 mService.addNotification(r);
2630 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002631
2632 verify(rh, times(1)).requestSort();
2633 }
2634
2635 @Test
2636 public void testRemoveAutogroup_requestsSort() throws Exception {
2637 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002638 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002639
2640 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2641 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002642 mService.addNotification(r);
2643 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002644
Julia Reynolds51710712017-07-19 13:48:07 -04002645 verify(rh, times(1)).requestSort();
2646 }
2647
2648 @Test
2649 public void testReaddAutogroup_noSort() throws Exception {
2650 RankingHandler rh = mock(RankingHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002651 mService.setRankingHandler(rh);
Julia Reynolds51710712017-07-19 13:48:07 -04002652
2653 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2654 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002655 mService.addNotification(r);
2656 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002657
2658 verify(rh, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002659 }
2660
2661 @Test
2662 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002663 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002664 NotificationManagerService.WorkerHandler handler = mock(
2665 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002666 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002667
2668 Map<String, Answer> answers = getSignalExtractorSideEffects();
2669 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002670 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002671 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002672 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002673
2674 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2675
Julia Reynolds503ed942017-10-04 16:04:56 -04002676 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002677 }
2678 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2679 }
2680
2681 @Test
2682 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002683 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002684 NotificationManagerService.WorkerHandler handler = mock(
2685 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002686 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002687
2688 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002689 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002690
Julia Reynolds503ed942017-10-04 16:04:56 -04002691 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002692 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002693 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002694
2695 @Test
2696 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002697 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002698 + "<ranking></ranking>"
2699 + "<enabled_listeners>"
2700 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2701 + "</enabled_listeners>"
2702 + "<enabled_assistants>"
2703 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2704 + "</enabled_assistants>"
2705 + "<dnd_apps>"
2706 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2707 + "</dnd_apps>"
2708 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002709 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002710 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2711 false,
2712 UserHandle.USER_ALL);
2713 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2714 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2715 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002716
2717 // numbers are inflated for setup
2718 verify(mListeners, times(1)).migrateToXml();
2719 verify(mConditionProviders, times(1)).migrateToXml();
2720 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002721 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002722 }
2723
2724 @Test
2725 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2726 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002727 + "<ranking></ranking>"
2728 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002729 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002730 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2731 false,
2732 UserHandle.USER_ALL);
2733 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2734 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2735 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002736
2737 // numbers are inflated for setup
2738 verify(mListeners, times(2)).migrateToXml();
2739 verify(mConditionProviders, times(2)).migrateToXml();
2740 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002741 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002742 }
2743
Annie Meng8b646fd2019-02-01 18:46:42 +00002744 @Test
2745 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2746 final String policyXml = "<notification-policy version=\"1\">"
2747 + "<ranking></ranking>"
2748 + "<enabled_listeners>"
2749 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2750 + "</enabled_listeners>"
2751 + "<enabled_assistants>"
2752 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2753 + "</enabled_assistants>"
2754 + "<dnd_apps>"
2755 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2756 + "</dnd_apps>"
2757 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002758 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00002759 mService.readPolicyXml(
2760 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2761 true,
2762 10);
2763 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2764 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2765 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2766 }
2767
2768 @Test
2769 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2770 final String policyXml = "<notification-policy version=\"1\">"
2771 + "<ranking></ranking>"
2772 + "<enabled_listeners>"
2773 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2774 + "</enabled_listeners>"
2775 + "<enabled_assistants>"
2776 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2777 + "</enabled_assistants>"
2778 + "<dnd_apps>"
2779 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2780 + "</dnd_apps>"
2781 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002782 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00002783 mService.readPolicyXml(
2784 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2785 true,
2786 10);
2787 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
2788 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
2789 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
2790 }
Beverlyd4f96492017-08-02 13:36:11 -04002791
2792 @Test
2793 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
2794 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002795 mService.mZenModeHelper = mZenModeHelper;
2796 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04002797 new Intent(Intent.ACTION_LOCALE_CHANGED));
2798
2799 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
2800 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002801
2802 @Test
2803 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06002804 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002805 final ApplicationInfo legacy = new ApplicationInfo();
2806 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
2807 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
2808 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002809 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
2810 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002811 getContext().setMockPackageManager(mPackageManagerClient);
2812
2813 Notification.Builder nb = new Notification.Builder(mContext,
2814 NotificationChannel.DEFAULT_CHANNEL_ID)
2815 .setContentTitle("foo")
2816 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002817 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002818 .setPriority(Notification.PRIORITY_MIN);
2819
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002820 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
2821 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002822
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002823 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
2824 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002825 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002826
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002827 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002828 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002829
2830 nb = new Notification.Builder(mContext)
2831 .setContentTitle("foo")
2832 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04002833 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002834 .setPriority(Notification.PRIORITY_MIN);
2835
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04002836 sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
2837 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002838
2839 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
2840 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2841 waitForIdle();
2842 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04002843 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002844
2845 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04002846 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002847 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
2848 }
Julia Reynolds503ed942017-10-04 16:04:56 -04002849
2850 @Test
2851 public void testStats_updatedOnDirectReply() throws Exception {
2852 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2853 mService.addNotification(r);
2854
2855 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
2856 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00002857 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04002858 }
2859
2860 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002861 public void testStats_updatedOnUserExpansion() throws Exception {
2862 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002863 mService.addNotification(r);
2864
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002865 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
2866 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002867 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002868 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002869
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002870 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
2871 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00002872 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04002873 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
2874 }
2875
2876 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002877 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
2878 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2879 mService.addNotification(r);
2880
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002881 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
2882 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002883 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002884 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
2885
Gustav Senntona8e38aa2019-01-22 14:55:39 +00002886 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
2887 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002888 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00002889 verify(mAssistants).notifyAssistantExpansionChangedLocked(
2890 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05002891 }
2892
2893 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04002894 public void testStats_updatedOnViewSettings() throws Exception {
2895 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2896 mService.addNotification(r);
2897
2898 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
2899 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
2900 }
2901
2902 @Test
2903 public void testStats_updatedOnVisibilityChanged() throws Exception {
2904 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2905 mService.addNotification(r);
2906
Dieter Hsud39f0d52018-04-14 02:08:30 +08002907 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002908 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2909 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
2910 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2911 mService.mNotificationDelegate.onNotificationVisibilityChanged(
2912 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
2913 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
2914 }
2915
2916 @Test
2917 public void testStats_dismissalSurface() 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(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04002922 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002923 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2924 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04002925 waitForIdle();
2926
2927 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
2928 }
2929
2930 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04002931 public void testStats_dismissalSentiment() throws Exception {
2932 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2933 mService.addNotification(r);
2934
2935 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
2936 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
2937 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
2938 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
2939 waitForIdle();
2940
2941 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
2942 r.getStats().getDismissalSentiment());
2943 }
2944
2945 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002946 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002947 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2948 mService.addNotification(r);
2949 NotificationManagerService.WorkerHandler handler = mock(
2950 NotificationManagerService.WorkerHandler.class);
2951 mService.setHandler(handler);
2952
Julia Reynolds70aaea72018-07-13 13:38:34 -04002953 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
2954
Julia Reynolds503ed942017-10-04 16:04:56 -04002955 Bundle signals = new Bundle();
2956 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04002957 USER_SENTIMENT_NEGATIVE);
2958 Adjustment adjustment = new Adjustment(
2959 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2960 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2961
2962 waitForIdle();
2963
2964 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2965 }
2966
2967 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05002968 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002969 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2970 mService.addNotification(r);
2971 NotificationManagerService.WorkerHandler handler = mock(
2972 NotificationManagerService.WorkerHandler.class);
2973 mService.setHandler(handler);
2974
2975 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04002976 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04002977 Adjustment adjustment = new Adjustment(
2978 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
2979 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
2980 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
2981
2982 waitForIdle();
2983
2984 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
2985 verify(handler, times(1)).scheduleCancelNotification(any());
2986 }
2987
2988 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04002989 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
2990 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2991 mService.addEnqueuedNotification(r);
2992 NotificationManagerService.WorkerHandler handler = mock(
2993 NotificationManagerService.WorkerHandler.class);
2994 mService.setHandler(handler);
2995 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
2996
2997 Bundle signals = new Bundle();
2998 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
2999 USER_SENTIMENT_NEGATIVE);
3000 Adjustment adjustment = new Adjustment(
3001 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3002 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3003
3004 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3005 }
3006
3007 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003008 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003009 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3010 mService.addEnqueuedNotification(r);
3011 NotificationManagerService.WorkerHandler handler = mock(
3012 NotificationManagerService.WorkerHandler.class);
3013 mService.setHandler(handler);
3014 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3015
3016 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003017 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003018 Adjustment adjustment = new Adjustment(
3019 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3020 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3021
3022 assertEquals(IMPORTANCE_LOW, r.getImportance());
3023 }
3024
3025 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003026 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3027 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3028 mService.addEnqueuedNotification(r);
3029 NotificationManagerService.WorkerHandler handler = mock(
3030 NotificationManagerService.WorkerHandler.class);
3031 mService.setHandler(handler);
3032 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3033
3034 Bundle signals = new Bundle();
3035 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3036 USER_SENTIMENT_NEGATIVE);
3037 Adjustment adjustment = new Adjustment(
3038 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3039 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3040
3041 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3042
3043 waitForIdle();
3044
3045 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3046 }
3047
3048 @Test
3049 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3050 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3051 mService.addNotification(r);
3052 NotificationManagerService.WorkerHandler handler = mock(
3053 NotificationManagerService.WorkerHandler.class);
3054 mService.setHandler(handler);
3055 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3056
3057 Bundle signals = new Bundle();
3058 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3059 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003060 Adjustment adjustment = new Adjustment(
3061 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3062 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3063
3064 waitForIdle();
3065
3066 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3067 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003068
3069 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003070 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3071 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3072 mService.addNotification(r);
3073 NotificationManagerService.WorkerHandler handler = mock(
3074 NotificationManagerService.WorkerHandler.class);
3075 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003076 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003077
3078 Bundle signals = new Bundle();
3079 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003080 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003081 Adjustment adjustment = new Adjustment(
3082 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3083 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3084
3085 waitForIdle();
3086
3087 verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
3088 }
3089
3090 @Test
3091 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3092 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3093 mService.addEnqueuedNotification(r);
3094 NotificationManagerService.WorkerHandler handler = mock(
3095 NotificationManagerService.WorkerHandler.class);
3096 mService.setHandler(handler);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003097 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003098
3099 Bundle signals = new Bundle();
3100 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003101 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003102 Adjustment adjustment = new Adjustment(
3103 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3104 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3105
Julia Reynolds70aaea72018-07-13 13:38:34 -04003106 assertEquals(USER_SENTIMENT_NEGATIVE,
Julia Reynolds666ccf02018-06-18 10:19:20 -04003107 r.getUserSentiment());
3108 }
3109
3110 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003111 public void testRestore() throws Exception {
3112 int systemChecks = mService.countSystemChecks;
3113 mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
3114 assertEquals(1, mService.countSystemChecks - systemChecks);
3115 }
3116
3117 @Test
3118 public void testBackup() throws Exception {
3119 int systemChecks = mService.countSystemChecks;
3120 mBinderService.getBackupPayload(1);
3121 assertEquals(1, mService.countSystemChecks - systemChecks);
3122 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003123
3124 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003125 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003126 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003127 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003128 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3129 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003130 message1.setData("",
3131 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003132 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003133 message2.setData("",
3134 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003135
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003136 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003137 .setContentTitle("foo")
3138 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3139 .setStyle(new Notification.MessagingStyle("")
3140 .addMessage(message1)
3141 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003142 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3143 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003144
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003145 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003146 reset(mUgm);
3147 reset(mUgmInternal);
3148 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003149 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
3150 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003151 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003152 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003153 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003154 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3155
3156 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003157 .setContentTitle("foo")
3158 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3159 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003160 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3161 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003162
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003163 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003164 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003165 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
3166 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003167 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3168 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003169
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003170 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003171 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003172 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
3173 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003174 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003175 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003176
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003177 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003178 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003179 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
3180 UserHandle.USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003181 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003182 anyInt(), anyInt());
3183 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003184
3185 @Test
Robin Leed107af62018-04-27 13:55:56 +02003186 public void testVisitUris() throws Exception {
3187 final Uri audioContents = Uri.parse("content://com.example/audio");
3188 final Uri backgroundImage = Uri.parse("content://com.example/background");
3189
3190 Bundle extras = new Bundle();
3191 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3192 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3193
3194 Notification n = new Notification.Builder(mContext, "a")
3195 .setContentTitle("notification with uris")
3196 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3197 .addExtras(extras)
3198 .build();
3199
3200 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3201 n.visitUris(visitor);
3202 verify(visitor, times(1)).accept(eq(audioContents));
3203 verify(visitor, times(1)).accept(eq(backgroundImage));
3204 }
3205
3206 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003207 public void testSetNotificationPolicy_preP_setOldFields() {
3208 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3209 mService.mZenModeHelper = mZenModeHelper;
3210 NotificationManager.Policy userPolicy =
3211 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3212 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3213
3214 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3215 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3216
3217 int expected = SUPPRESSED_EFFECT_BADGE
3218 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003219 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3220 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003221 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3222
3223 assertEquals(expected, actual);
3224 }
3225
3226 @Test
3227 public void testSetNotificationPolicy_preP_setNewFields() {
3228 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3229 mService.mZenModeHelper = mZenModeHelper;
3230 NotificationManager.Policy userPolicy =
3231 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3232 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3233
3234 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3235 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3236
3237 int expected = SUPPRESSED_EFFECT_BADGE;
3238 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3239
3240 assertEquals(expected, actual);
3241 }
3242
3243 @Test
3244 public void testSetNotificationPolicy_preP_setOldNewFields() {
3245 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3246 mService.mZenModeHelper = mZenModeHelper;
3247 NotificationManager.Policy userPolicy =
3248 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3249 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3250
3251 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3252 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3253
3254 int expected =
3255 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3256 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3257
3258 assertEquals(expected, actual);
3259 }
3260
3261 @Test
3262 public void testSetNotificationPolicy_P_setOldFields() {
3263 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3264 mService.mZenModeHelper = mZenModeHelper;
3265 NotificationManager.Policy userPolicy =
3266 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3267 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3268
3269 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3270 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3271
3272 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3273 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3274 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3275 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3276
3277 assertEquals(expected, actual);
3278 }
3279
3280 @Test
3281 public void testSetNotificationPolicy_P_setNewFields() {
3282 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3283 mService.mZenModeHelper = mZenModeHelper;
3284 NotificationManager.Policy userPolicy =
3285 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3286 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3287
3288 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3289 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3290 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3291
3292 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3293 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3294 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3295 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3296
3297 assertEquals(expected, actual);
3298 }
3299
3300 @Test
3301 public void testSetNotificationPolicy_P_setOldNewFields() {
3302 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3303 mService.mZenModeHelper = mZenModeHelper;
3304 NotificationManager.Policy userPolicy =
3305 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3306 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3307
3308 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3309 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3310
3311 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3312 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3313
3314 assertEquals(expected, actual);
3315
3316 appPolicy = new NotificationManager.Policy(0, 0, 0,
3317 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3318 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3319
3320 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3321 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3322 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3323
3324 assertEquals(expected, actual);
3325 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003326
3327 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003328 public void testVisualDifference_foreground() {
3329 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3330 .setContentTitle("foo");
3331 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3332 nb1.build(), new UserHandle(mUid), null, 0);
3333 NotificationRecord r1 =
3334 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3335
3336 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3337 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3338 .setContentTitle("bar");
3339 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3340 nb2.build(), new UserHandle(mUid), null, 0);
3341 NotificationRecord r2 =
3342 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3343
3344 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3345 }
3346
3347 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003348 public void testVisualDifference_diffTitle() {
3349 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3350 .setContentTitle("foo");
3351 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3352 nb1.build(), new UserHandle(mUid), null, 0);
3353 NotificationRecord r1 =
3354 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3355
3356 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3357 .setContentTitle("bar");
3358 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3359 nb2.build(), new UserHandle(mUid), null, 0);
3360 NotificationRecord r2 =
3361 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3362
3363 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3364 }
3365
3366 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003367 public void testVisualDifference_inboxStyle() {
3368 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3369 .setStyle(new Notification.InboxStyle()
3370 .addLine("line1").addLine("line2"));
3371 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3372 nb1.build(), new UserHandle(mUid), null, 0);
3373 NotificationRecord r1 =
3374 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3375
3376 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3377 .setStyle(new Notification.InboxStyle()
3378 .addLine("line1").addLine("line2_changed"));
3379 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3380 nb2.build(), new UserHandle(mUid), null, 0);
3381 NotificationRecord r2 =
3382 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3383
3384 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3385
3386 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3387 .setStyle(new Notification.InboxStyle()
3388 .addLine("line1"));
3389 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3390 nb3.build(), new UserHandle(mUid), null, 0);
3391 NotificationRecord r3 =
3392 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3393
3394 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3395
3396 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3397 .setStyle(new Notification.InboxStyle()
3398 .addLine("line1").addLine("line2").addLine("line3"));
3399 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3400 nb4.build(), new UserHandle(mUid), null, 0);
3401 NotificationRecord r4 =
3402 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3403
3404 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3405
3406 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3407 .setContentText("not an inbox");
3408 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3409 nb5.build(), new UserHandle(mUid), null, 0);
3410 NotificationRecord r5 =
3411 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3412
3413 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3414 }
3415
3416 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003417 public void testVisualDifference_diffText() {
3418 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3419 .setContentText("foo");
3420 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3421 nb1.build(), new UserHandle(mUid), null, 0);
3422 NotificationRecord r1 =
3423 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3424
3425 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3426 .setContentText("bar");
3427 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3428 nb2.build(), new UserHandle(mUid), null, 0);
3429 NotificationRecord r2 =
3430 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3431
3432 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3433 }
3434
3435 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003436 public void testVisualDifference_sameText() {
3437 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3438 .setContentText("foo");
3439 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3440 nb1.build(), new UserHandle(mUid), null, 0);
3441 NotificationRecord r1 =
3442 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3443
3444 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3445 .setContentText("foo");
3446 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3447 nb2.build(), new UserHandle(mUid), null, 0);
3448 NotificationRecord r2 =
3449 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3450
3451 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3452 }
3453
3454 @Test
3455 public void testVisualDifference_sameTextButStyled() {
3456 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3457 .setContentText(Html.fromHtml("<b>foo</b>"));
3458 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3459 nb1.build(), new UserHandle(mUid), null, 0);
3460 NotificationRecord r1 =
3461 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3462
3463 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3464 .setContentText(Html.fromHtml("<b>foo</b>"));
3465 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3466 nb2.build(), new UserHandle(mUid), null, 0);
3467 NotificationRecord r2 =
3468 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3469
3470 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3471 }
3472
3473 @Test
3474 public void testVisualDifference_diffTextButStyled() {
3475 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3476 .setContentText(Html.fromHtml("<b>foo</b>"));
3477 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3478 nb1.build(), new UserHandle(mUid), null, 0);
3479 NotificationRecord r1 =
3480 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3481
3482 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3483 .setContentText(Html.fromHtml("<b>bar</b>"));
3484 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3485 nb2.build(), new UserHandle(mUid), null, 0);
3486 NotificationRecord r2 =
3487 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3488
3489 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3490 }
3491
3492 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003493 public void testVisualDifference_diffProgress() {
3494 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3495 .setProgress(100, 90, false);
3496 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3497 nb1.build(), new UserHandle(mUid), null, 0);
3498 NotificationRecord r1 =
3499 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3500
3501 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3502 .setProgress(100, 100, false);
3503 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3504 nb2.build(), new UserHandle(mUid), null, 0);
3505 NotificationRecord r2 =
3506 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3507
3508 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3509 }
3510
3511 @Test
3512 public void testVisualDifference_diffProgressNotDone() {
3513 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3514 .setProgress(100, 90, false);
3515 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3516 nb1.build(), new UserHandle(mUid), null, 0);
3517 NotificationRecord r1 =
3518 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3519
3520 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3521 .setProgress(100, 91, false);
3522 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3523 nb2.build(), new UserHandle(mUid), null, 0);
3524 NotificationRecord r2 =
3525 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3526
3527 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3528 }
Beverly5a20a5e2018-03-06 15:02:44 -05003529
3530 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003531 public void testVisualDifference_sameProgressStillDone() {
3532 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3533 .setProgress(100, 100, false);
3534 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3535 nb1.build(), new UserHandle(mUid), null, 0);
3536 NotificationRecord r1 =
3537 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3538
3539 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3540 .setProgress(100, 100, false);
3541 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3542 nb2.build(), new UserHandle(mUid), null, 0);
3543 NotificationRecord r2 =
3544 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3545
3546 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3547 }
3548
3549 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003550 public void testVisualDifference_summary() {
3551 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3552 .setGroup("bananas")
3553 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3554 .setContentText("foo");
3555 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3556 nb1.build(), new UserHandle(mUid), null, 0);
3557 NotificationRecord r1 =
3558 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3559
3560 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3561 .setGroup("bananas")
3562 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3563 .setContentText("bar");
3564 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3565 nb2.build(), new UserHandle(mUid), null, 0);
3566 NotificationRecord r2 =
3567 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3568
3569 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3570 }
3571
3572 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003573 public void testVisualDifference_summaryNewNotification() {
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(null, r2));
3584 }
3585
3586 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003587 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3588 // post 2 notification from this package
3589 final NotificationRecord notif1 = generateNotificationRecord(
3590 mTestNotificationChannel, 1, null, true);
3591 final NotificationRecord notif2 = generateNotificationRecord(
3592 mTestNotificationChannel, 2, null, false);
3593 mService.addNotification(notif1);
3594 mService.addNotification(notif2);
3595
3596 // on broadcast, hide the 2 notifications
3597 mService.simulatePackageSuspendBroadcast(true, PKG);
3598 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3599 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3600 assertEquals(2, captorHide.getValue().size());
3601
3602 // on broadcast, unhide the 2 notifications
3603 mService.simulatePackageSuspendBroadcast(false, PKG);
3604 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3605 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3606 assertEquals(2, captorUnhide.getValue().size());
3607 }
3608
3609 @Test
3610 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3611 // post 2 notification from this package
3612 final NotificationRecord notif1 = generateNotificationRecord(
3613 mTestNotificationChannel, 1, null, true);
3614 final NotificationRecord notif2 = generateNotificationRecord(
3615 mTestNotificationChannel, 2, null, false);
3616 mService.addNotification(notif1);
3617 mService.addNotification(notif2);
3618
3619 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3620 mService.simulatePackageSuspendBroadcast(true, "test_package");
3621 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3622 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3623 assertEquals(0, captor.getValue().size());
3624 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003625
3626 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003627 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3628 // Post 2 notifications from 2 packages
3629 NotificationRecord pkgA = new NotificationRecord(mContext,
3630 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3631 mService.addNotification(pkgA);
3632 NotificationRecord pkgB = new NotificationRecord(mContext,
3633 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3634 mService.addNotification(pkgB);
3635
3636 // on broadcast, hide one of the packages
3637 mService.simulatePackageDistractionBroadcast(
3638 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3639 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3640 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3641 assertEquals(1, captorHide.getValue().size());
3642 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3643
3644 // on broadcast, unhide the package
3645 mService.simulatePackageDistractionBroadcast(
3646 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3647 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3648 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3649 assertEquals(1, captorUnhide.getValue().size());
3650 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3651 }
3652
3653 @Test
3654 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3655 // Post 2 notifications from 2 packages
3656 NotificationRecord pkgA = new NotificationRecord(mContext,
3657 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3658 mService.addNotification(pkgA);
3659 NotificationRecord pkgB = new NotificationRecord(mContext,
3660 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3661 mService.addNotification(pkgB);
3662
3663 // on broadcast, hide one of the packages
3664 mService.simulatePackageDistractionBroadcast(
3665 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3666 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003667
3668 // should be called only once.
3669 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003670 assertEquals(2, captorHide.getValue().size());
3671 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3672 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3673
3674 // on broadcast, unhide the package
3675 mService.simulatePackageDistractionBroadcast(
3676 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3677 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003678
3679 // should be called only once.
3680 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003681 assertEquals(2, captorUnhide.getValue().size());
3682 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3683 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3684 }
3685
3686 @Test
3687 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3688 // post notification from this package
3689 final NotificationRecord notif1 = generateNotificationRecord(
3690 mTestNotificationChannel, 1, null, true);
3691 mService.addNotification(notif1);
3692
3693 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3694 mService.simulatePackageDistractionBroadcast(
3695 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3696 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3697 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3698 assertEquals(0, captor.getValue().size());
3699 }
3700
3701 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003702 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3703 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3704 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3705 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3706 .thenReturn(new String[] {"a", "b", "c"});
3707 when(mContext.getResources()).thenReturn(mResources);
3708
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003709 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003710 }
3711
3712 @Test
3713 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3714 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3715 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3716 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3717 .thenReturn(new String[] {"a", "b", "c"});
3718 when(mContext.getResources()).thenReturn(mResources);
3719
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003720 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003721 }
3722
3723 @Test
3724 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3725 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3726 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3727 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3728 .thenReturn(new String[] {"a", "b", "c"});
3729 when(mContext.getResources()).thenReturn(mResources);
3730
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003731 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003732 }
3733
3734 @Test
3735 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3736 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3737 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3738 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3739 .thenReturn(new String[] {"a", "b", "c"});
3740 when(mContext.getResources()).thenReturn(mResources);
3741
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003742 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003743 }
3744
3745 @Test
3746 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3747 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3748 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3749 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3750 .thenReturn(new String[] {"a", "b", "c"});
3751 when(mContext.getResources()).thenReturn(mResources);
3752
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003753 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003754 }
3755
3756 @Test
3757 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
3758 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3759 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3760 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3761 .thenReturn(new String[] {"a", "b", "c"});
3762 when(mContext.getResources()).thenReturn(mResources);
3763
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003764 assertEquals(true, mService.canUseManagedServices("d", 0, null));
3765 }
3766
3767 @Test
3768 public void testCanUseManagedServices_hasPermission() throws Exception {
3769 when(mPackageManager.checkPermission("perm", "pkg", 0))
3770 .thenReturn(PackageManager.PERMISSION_GRANTED);
3771
3772 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
3773 }
3774
3775 @Test
3776 public void testCanUseManagedServices_noPermission() throws Exception {
3777 when(mPackageManager.checkPermission("perm", "pkg", 0))
3778 .thenReturn(PackageManager.PERMISSION_DENIED);
3779
3780 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
3781 }
3782
3783 @Test
3784 public void testCanUseManagedServices_permDoesNotMatter() {
3785 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003786 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003787
3788 @Test
3789 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
3790 final NotificationRecord r = generateNotificationRecord(
3791 mTestNotificationChannel, 1, null, true);
3792 r.setTextChanged(true);
3793 mService.addNotification(r);
3794
3795 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
3796 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
3797 new NotificationVisibility[]{});
3798
3799 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3800 }
3801
3802 @Test
3803 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
3804 throws RemoteException {
3805 final NotificationRecord r = generateNotificationRecord(
3806 mTestNotificationChannel, 1, null, true);
3807 r.setTextChanged(true);
3808 mService.addNotification(r);
3809
3810 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
3811
3812 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
3813 }
3814
3815 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003816 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04003817 throws RemoteException {
3818 final NotificationRecord r = generateNotificationRecord(
3819 mTestNotificationChannel, 1, null, true);
3820 r.setInterruptive(true);
3821 mService.addNotification(r);
3822
3823 mService.maybeRecordInterruptionLocked(r);
3824 mService.maybeRecordInterruptionLocked(r);
3825
3826 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
3827 anyString(), anyString(), anyInt());
3828 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003829
3830 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08003831 public void testBubble() throws Exception {
3832 mBinderService.setBubblesAllowed(PKG, mUid, false);
3833 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05003834 }
3835
3836 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08003837 public void testUserApprovedBubblesForPackage() throws Exception {
3838 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3839 mBinderService.setBubblesAllowed(PKG, mUid, true);
3840 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3841 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3842 }
3843
3844 @Test
3845 public void testUserRejectsBubblesForPackage() throws Exception {
3846 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3847 mBinderService.setBubblesAllowed(PKG, mUid, false);
3848 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
3849 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
3850 }
3851
3852 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003853 public void testIsCallerInstantApp_primaryUser() throws Exception {
3854 ApplicationInfo info = new ApplicationInfo();
3855 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3856 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04003857 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04003858
Julia Reynolds268647a2018-10-25 16:54:27 -04003859 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003860
3861 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04003862 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003863 }
3864
3865 @Test
3866 public void testIsCallerInstantApp_secondaryUser() throws Exception {
3867 ApplicationInfo info = new ApplicationInfo();
3868 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3869 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3870 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
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(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04003874 }
3875
3876 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04003877 public void testIsCallerInstantApp_userAllNotification() throws Exception {
3878 ApplicationInfo info = new ApplicationInfo();
3879 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
3880 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(UserHandle.USER_SYSTEM)))
3881 .thenReturn(info);
3882 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
3883
3884 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
3885
3886 info.privateFlags = 0;
3887 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
3888 }
3889
3890 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04003891 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
3892 ApplicationInfo info = new ApplicationInfo();
3893 info.uid = Binder.getCallingUid();
3894 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
3895 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
3896
3897 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
3898
3899 assertEquals(info.uid, actualUid);
3900 }
3901
3902 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003903 public void testResolveNotificationUid_sameApp() throws Exception {
3904 ApplicationInfo info = new ApplicationInfo();
3905 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04003906 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003907
3908 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
3909
3910 assertEquals(info.uid, actualUid);
3911 }
3912
3913 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003914 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003915 ApplicationInfo info = new ApplicationInfo();
3916 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003917 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003918
Julia Reynoldsecc1b572018-10-01 16:19:24 -04003919 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
3920
3921 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003922 }
3923
3924 @Test
3925 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
3926 ApplicationInfo info = new ApplicationInfo();
3927 info.uid = 1356347;
3928 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
3929
3930 try {
3931 mService.resolveNotificationUid("caller", "caller", 9, 0);
3932 fail("Incorrect uid didn't throw security exception");
3933 } catch (SecurityException e) {
3934 // yay
3935 }
3936 }
3937
3938 @Test
3939 public void testResolveNotificationUid_delegateAllowed() throws Exception {
3940 int expectedUid = 123;
3941
3942 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3943 mService.setPreferencesHelper(mPreferencesHelper);
3944 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
3945 .thenReturn(true);
3946
3947 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
3948 }
3949
3950 @Test
3951 public void testResolveNotificationUid_androidAllowed() throws Exception {
3952 int expectedUid = 123;
3953
3954 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
3955 // no delegate
3956
3957 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
3958 }
3959
3960 @Test
3961 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
3962 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
3963 // no delegate
3964
3965 try {
3966 mService.resolveNotificationUid("caller", "target", 9, 0);
3967 fail("Incorrect uid didn't throw security exception");
3968 } catch (SecurityException e) {
3969 // yay
3970 }
3971 }
Julia Reynolds564273f2018-09-13 15:53:11 -04003972
3973 @Test
3974 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
3975 Notification n = new Notification.Builder(mContext, "").build();
3976 n.flags |= FLAG_FOREGROUND_SERVICE;
3977
3978 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3979 n, new UserHandle(mUid), null, 0);
3980 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3981
3982 mService.addEnqueuedNotification(r);
3983
3984 mInternalService.removeForegroundServiceFlagFromNotification(
3985 PKG, r.sbn.getId(), r.sbn.getUserId());
3986
3987 waitForIdle();
3988
3989 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
3990 }
3991
3992 @Test
3993 public void testRemoveForegroundServiceFlagFromNotification_posted() {
3994 Notification n = new Notification.Builder(mContext, "").build();
3995 n.flags |= FLAG_FOREGROUND_SERVICE;
3996
3997 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
3998 n, new UserHandle(mUid), null, 0);
3999 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4000
4001 mService.addNotification(r);
4002
4003 mInternalService.removeForegroundServiceFlagFromNotification(
4004 PKG, r.sbn.getId(), r.sbn.getUserId());
4005
4006 waitForIdle();
4007
4008 ArgumentCaptor<NotificationRecord> captor =
4009 ArgumentCaptor.forClass(NotificationRecord.class);
4010 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4011
4012 assertEquals(0, captor.getValue().getNotification().flags);
4013 }
Beverly58b24532018-10-02 09:08:23 -04004014
4015 @Test
4016 public void testAllowForegroundToasts() throws Exception {
4017 final String testPackage = "testPackageName";
4018 assertEquals(0, mService.mToastQueue.size());
4019 mService.isSystemUid = false;
4020
4021 // package is not suspended
4022 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4023 .thenReturn(false);
4024
4025 // notifications from this package are blocked by the user
4026 mService.setPreferencesHelper(mPreferencesHelper);
4027 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4028
4029 // this app is in the foreground
4030 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4031
4032 // enqueue toast -> toast should still enqueue
4033 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4034 new TestableToastCallback(), 2000, 0);
4035 assertEquals(1, mService.mToastQueue.size());
4036 }
4037
4038 @Test
4039 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4040 final String testPackage = "testPackageName";
4041 assertEquals(0, mService.mToastQueue.size());
4042 mService.isSystemUid = false;
4043
4044 // package is suspended
4045 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4046 .thenReturn(true);
4047
4048 // notifications from this package are NOT blocked by the user
4049 mService.setPreferencesHelper(mPreferencesHelper);
4050 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4051
4052 // enqueue toast -> no toasts enqueued
4053 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4054 new TestableToastCallback(), 2000, 0);
4055 assertEquals(0, mService.mToastQueue.size());
4056 }
4057
4058 @Test
4059 public void testDisallowToastsFromBlockedApps() throws Exception {
4060 final String testPackage = "testPackageName";
4061 assertEquals(0, mService.mToastQueue.size());
4062 mService.isSystemUid = false;
4063
4064 // package is not suspended
4065 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4066 .thenReturn(false);
4067
4068 // notifications from this package are blocked by the user
4069 mService.setPreferencesHelper(mPreferencesHelper);
4070 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4071
4072 // this app is NOT in the foreground
4073 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4074
4075 // enqueue toast -> no toasts enqueued
4076 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4077 new TestableToastCallback(), 2000, 0);
4078 assertEquals(0, mService.mToastQueue.size());
4079 }
4080
4081 @Test
4082 public void testAlwaysAllowSystemToasts() throws Exception {
4083 final String testPackage = "testPackageName";
4084 assertEquals(0, mService.mToastQueue.size());
4085 mService.isSystemUid = true;
4086
4087 // package is suspended
4088 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4089 .thenReturn(true);
4090
4091 // notifications from this package ARE blocked by the user
4092 mService.setPreferencesHelper(mPreferencesHelper);
4093 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4094
4095 // this app is NOT in the foreground
4096 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4097
4098 // enqueue toast -> system toast can still be enqueued
4099 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4100 new TestableToastCallback(), 2000, 0);
4101 assertEquals(1, mService.mToastQueue.size());
4102 }
Tony Mak29996702018-11-26 16:23:34 +00004103
4104 @Test
4105 public void testOnNotificationSmartReplySent() {
4106 final int replyIndex = 2;
4107 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004108 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004109 final boolean generatedByAssistant = true;
4110
4111 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004112 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004113 mService.addNotification(r);
4114
4115 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004116 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4117 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004118 verify(mAssistants).notifyAssistantSuggestedReplySent(
4119 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4120 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004121
4122 @Test
4123 public void testOnNotificationActionClick() {
4124 final int actionIndex = 2;
4125 final Notification.Action action =
4126 new Notification.Action.Builder(null, "text", null).build();
4127 final boolean generatedByAssistant = false;
4128
4129 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4130 mService.addNotification(r);
4131
4132 NotificationVisibility notificationVisibility =
4133 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4134 mService.mNotificationDelegate.onNotificationActionClick(
4135 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4136 generatedByAssistant);
4137 verify(mAssistants).notifyAssistantActionClicked(
4138 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4139 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004140
4141 @Test
4142 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4143 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4144 mService.addNotification(r);
4145
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004146 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4147 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004148 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4149 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4150 };
4151 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4152 new NotificationVisibility[0]);
4153
4154 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4155 }
4156
4157 @Test
4158 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4159 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4160 mService.addNotification(r);
4161
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004162 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4163 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004164
4165 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4166 }
4167
4168 @Test
4169 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4170 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4171 mService.addNotification(r);
4172
Julia Reynolds95334132018-12-19 11:15:35 -05004173 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004174 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4175 };
4176 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4177 new NotificationVisibility[0]);
4178
4179 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4180 }
Julia Reynolds95334132018-12-19 11:15:35 -05004181
4182 public void testReportSeen_delegated() {
4183 Notification.Builder nb =
4184 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4185 .setContentTitle("foo")
4186 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4187
4188 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4189 nb.build(), new UserHandle(mUid), null, 0);
4190 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4191
4192 mService.reportSeen(r);
4193 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4194
4195 }
4196
4197 @Test
4198 public void testReportSeen_notDelegated() {
4199 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4200
4201 mService.reportSeen(r);
4202 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4203 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004204
4205 @Test
4206 public void testNotificationStats_notificationError() {
4207 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4208 mService.addNotification(r);
4209
4210 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4211 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4212 new UserHandle(mUid), null, 0);
4213 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4214 mService.addEnqueuedNotification(update);
4215 assertNull(update.sbn.getNotification().getSmallIcon());
4216
4217 NotificationManagerService.PostNotificationRunnable runnable =
4218 mService.new PostNotificationRunnable(update.getKey());
4219 runnable.run();
4220 waitForIdle();
4221
4222 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4223 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4224 assertNotNull(captor.getValue());
4225 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004226
4227 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004228 public void testCanNotifyAsUser_crossUser() throws Exception {
4229 // same user no problem
4230 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4231
4232 // cross user, no permission, problem
4233 try {
4234 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4235 fail("Should not be callable cross user without cross user permission");
4236 } catch (SecurityException e) {
4237 // good
4238 }
4239
4240 // cross user, with permission, no problem
4241 TestablePermissions perms = mContext.getTestablePermissions();
4242 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4243 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4244 }
4245
4246 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004247 public void testgetNotificationChannels_crossUser() throws Exception {
4248 // same user no problem
4249 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4250
4251 // cross user, no permission, problem
4252 try {
4253 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4254 fail("Should not be callable cross user without cross user permission");
4255 } catch (SecurityException e) {
4256 // good
4257 }
4258
4259 // cross user, with permission, no problem
4260 TestablePermissions perms = mContext.getTestablePermissions();
4261 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4262 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4263 }
4264
4265 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004266 public void setDefaultAssistantForUser_fromConfigXml() {
4267 clearDeviceConfig();
4268 ComponentName xmlConfig = new ComponentName("config", "xml");
4269 when(mResources
4270 .getString(
4271 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4272 .thenReturn(xmlConfig.flattenToString());
4273 when(mContext.getResources()).thenReturn(mResources);
4274 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4275 .thenReturn(Collections.singleton(xmlConfig));
4276 mService.setNotificationAssistantAccessGrantedCallback(
4277 mNotificationAssistantAccessGrantedCallback);
4278
4279 mService.setDefaultAssistantForUser(0);
4280
4281 verify(mNotificationAssistantAccessGrantedCallback)
4282 .onGranted(eq(xmlConfig), eq(0), eq(true));
4283 }
4284
4285 @Test
4286 public void setDefaultAssistantForUser_fromDeviceConfig() {
4287 ComponentName xmlConfig = new ComponentName("xml", "config");
4288 ComponentName deviceConfig = new ComponentName("device", "config");
4289 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4290 when(mResources
4291 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4292 .thenReturn(xmlConfig.flattenToString());
4293 when(mContext.getResources()).thenReturn(mResources);
4294 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4295 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
4296 mService.setNotificationAssistantAccessGrantedCallback(
4297 mNotificationAssistantAccessGrantedCallback);
4298
4299 mService.setDefaultAssistantForUser(0);
4300
4301 verify(mNotificationAssistantAccessGrantedCallback)
4302 .onGranted(eq(deviceConfig), eq(0), eq(true));
4303 }
4304
4305 @Test
4306 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4307 ComponentName xmlConfig = new ComponentName("xml", "config");
4308 ComponentName deviceConfig = new ComponentName("device", "config");
4309 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4310 when(mResources
4311 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4312 .thenReturn(xmlConfig.flattenToString());
4313 when(mContext.getResources()).thenReturn(mResources);
4314 // Only xmlConfig is valid, deviceConfig is not.
4315 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
4316 .thenReturn(Collections.singleton(xmlConfig));
4317 mService.setNotificationAssistantAccessGrantedCallback(
4318 mNotificationAssistantAccessGrantedCallback);
4319
4320 mService.setDefaultAssistantForUser(0);
4321
4322 verify(mNotificationAssistantAccessGrantedCallback)
4323 .onGranted(eq(xmlConfig), eq(0), eq(true));
4324 }
4325
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004326 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004327 public void testFlagBubble() throws RemoteException {
4328 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004329 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004330
4331 // Notif with bubble metadata but not our other misc requirements
4332 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4333 null /* tvExtender */, true /* isBubble */);
4334
4335 // Say we're foreground
4336 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4337 IMPORTANCE_FOREGROUND);
4338
4339 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4340 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4341 waitForIdle();
4342
4343 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4344 assertEquals(1, notifs.length);
4345 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4346 assertTrue(mService.getNotificationRecord(
4347 nr.sbn.getKey()).getNotification().isBubbleNotification());
4348 }
4349
4350 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004351 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4352 // Bubbles are allowed!
4353 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4354
4355 // Notif with bubble metadata but not our other misc requirements
4356 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4357 null /* tvExtender */, true /* isBubble */);
4358
4359 // Say we're foreground
4360 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4361 IMPORTANCE_FOREGROUND);
4362
4363 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4364 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4365 waitForIdle();
4366
4367 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4368 assertEquals(1, notifs.length);
4369 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4370 assertFalse(mService.getNotificationRecord(
4371 nr.sbn.getKey()).getNotification().isBubbleNotification());
4372 }
4373
4374 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004375 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004376 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004377 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004378
Mady Mellorbe797962019-04-01 16:04:24 -07004379 // Notif with bubble metadata but not our other misc requirements
4380 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4381 null /* tvExtender */, true /* isBubble */);
4382
4383 // Say we're foreground
4384 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4385 IMPORTANCE_FOREGROUND);
4386
4387 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4388 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4389 waitForIdle();
4390
4391 // yes allowed, yes foreground, yes bubble
4392 assertTrue(mService.getNotificationRecord(
4393 nr.sbn.getKey()).getNotification().isBubbleNotification());
4394 }
4395
4396 @Test
4397 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4398 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004399 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004400
4401 // Notif with bubble metadata but not our other misc requirements
4402 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4403 null /* tvExtender */, true /* isBubble */);
4404
4405 // Make sure we're NOT foreground
4406 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4407 IMPORTANCE_VISIBLE);
4408
4409 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4410 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4411 waitForIdle();
4412
4413 // yes allowed but NOT foreground, no bubble
4414 assertFalse(mService.getNotificationRecord(
4415 nr.sbn.getKey()).getNotification().isBubbleNotification());
4416 }
4417
4418 @Test
4419 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4420 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004421 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004422
4423 // Notif with bubble metadata but not our other misc requirements
4424 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4425 null /* tvExtender */, true /* isBubble */);
4426
4427 // Send notif when we're foreground
4428 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4429 IMPORTANCE_FOREGROUND);
4430 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4431 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4432 waitForIdle();
4433
4434 // yes allowed, yes foreground, yes bubble
4435 assertTrue(mService.getNotificationRecord(
4436 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4437
4438 // Send a new update when we're not foreground
4439 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4440 null /* tvExtender */, true /* isBubble */);
4441
4442 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4443 IMPORTANCE_VISIBLE);
4444 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4445 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4446 waitForIdle();
4447
4448 // yes allowed, previously foreground / flagged, yes bubble
4449 assertTrue(mService.getNotificationRecord(
4450 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4451
4452 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4453 assertEquals(1, notifs2.length);
4454 assertEquals(1, mService.getNotificationRecordCount());
4455 }
4456
4457 @Test
4458 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4459 throws RemoteException {
4460 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004461 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004462
4463 // Notif with bubble metadata but not our other misc requirements
4464 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4465 null /* tvExtender */, true /* isBubble */);
4466
4467 // Send notif when we're foreground
4468 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4469 IMPORTANCE_FOREGROUND);
4470 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4471 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4472 waitForIdle();
4473
4474 // yes allowed, yes foreground, yes bubble
4475 assertTrue(mService.getNotificationRecord(
4476 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4477
4478 // Remove the bubble
4479 mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(),
4480 nr1.sbn.getUserId());
4481 waitForIdle();
4482
4483 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4484 assertEquals(0, notifs.length);
4485 assertEquals(0, mService.getNotificationRecordCount());
4486
4487 // Send a new update when we're not foreground
4488 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4489 null /* tvExtender */, true /* isBubble */);
4490
4491 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4492 IMPORTANCE_VISIBLE);
4493 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
4494 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4495 waitForIdle();
4496
4497 // yes allowed, but was removed & no foreground, so no bubble
4498 assertFalse(mService.getNotificationRecord(
4499 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4500
4501 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4502 assertEquals(1, notifs2.length);
4503 assertEquals(1, mService.getNotificationRecordCount());
4504 }
4505
4506 @Test
4507 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4508 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004509 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004510
4511 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004512 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004513 // Give it a person
4514 Person person = new Person.Builder()
4515 .setName("bubblebot")
4516 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004517 // It needs remote input to be bubble-able
4518 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4519 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4520 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4521 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4522 inputIntent).addRemoteInput(remoteInput)
4523 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004524 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004525 Notification.Builder nb = new Notification.Builder(mContext,
4526 mTestNotificationChannel.getId())
4527 .setContentTitle("foo")
4528 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004529 .setStyle(new Notification.MessagingStyle(person)
4530 .setConversationTitle("Bubble Chat")
4531 .addMessage("Hello?",
4532 SystemClock.currentThreadTimeMillis() - 300000, person)
4533 .addMessage("Is it me you're looking for?",
4534 SystemClock.currentThreadTimeMillis(), person)
4535 )
Mady Mellora10448e2019-04-26 13:50:58 -07004536 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -07004537 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4538
4539 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4540 nb.build(), new UserHandle(mUid), null, 0);
4541 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4542
4543 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4544 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4545 waitForIdle();
4546
4547 // yes allowed, yes messaging, yes bubble
4548 assertTrue(mService.getNotificationRecord(
4549 sbn.getKey()).getNotification().isBubbleNotification());
4550 }
4551
4552 @Test
4553 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4554 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004555 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004556
4557 // Give it bubble metadata
4558 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4559 // Give it a person
4560 Person person = new Person.Builder()
4561 .setName("bubblebot")
4562 .build();
4563 // Make it a phone call
4564 Notification.Builder nb = new Notification.Builder(mContext,
4565 mTestNotificationChannel.getId())
4566 .setCategory(CATEGORY_CALL)
4567 .addPerson(person)
4568 .setContentTitle("foo")
4569 .setBubbleMetadata(data)
4570 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4571
4572 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4573 nb.build(), new UserHandle(mUid), null, 0);
4574 // Make sure it has foreground service
4575 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4576 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4577
4578 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4579 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4580 waitForIdle();
4581
4582 // yes phone call, yes person, yes foreground service, yes bubble
4583 assertTrue(mService.getNotificationRecord(
4584 sbn.getKey()).getNotification().isBubbleNotification());
4585 }
4586
4587 @Test
4588 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4589 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004590 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004591
4592 // Give it bubble metadata
4593 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4594 // Give it a person
4595 Person person = new Person.Builder()
4596 .setName("bubblebot")
4597 .build();
4598 // Make it a phone call
4599 Notification.Builder nb = new Notification.Builder(mContext,
4600 mTestNotificationChannel.getId())
4601 .setCategory(CATEGORY_CALL)
4602 .addPerson(person)
4603 .setContentTitle("foo")
4604 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004605 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4606
4607 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4608 nb.build(), new UserHandle(mUid), null, 0);
4609 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4610
4611 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4612 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4613 waitForIdle();
4614
Mady Mellorbe797962019-04-01 16:04:24 -07004615 // yes phone call, yes person, NO foreground service, no bubble
4616 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004617 sbn.getKey()).getNotification().isBubbleNotification());
4618 }
4619
4620 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004621 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4622 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004623 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004624
4625 // Give it bubble metadata
4626 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4627 // Make it a phone call
4628 Notification.Builder nb = new Notification.Builder(mContext,
4629 mTestNotificationChannel.getId())
4630 .setCategory(CATEGORY_CALL)
4631 .setContentTitle("foo")
4632 .setBubbleMetadata(data)
4633 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4634
4635 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4636 nb.build(), new UserHandle(mUid), null, 0);
4637 // Make sure it has foreground service
4638 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4639 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4640
4641 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4642 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4643 waitForIdle();
4644
4645 // yes phone call, yes foreground service, BUT NO person, no bubble
4646 assertFalse(mService.getNotificationRecord(
4647 sbn.getKey()).getNotification().isBubbleNotification());
4648 }
4649
4650 @Test
4651 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4652 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004653 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004654
4655 // Give it bubble metadata
4656 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4657 // Give it a person
4658 Person person = new Person.Builder()
4659 .setName("bubblebot")
4660 .build();
4661 // No category
4662 Notification.Builder nb = new Notification.Builder(mContext,
4663 mTestNotificationChannel.getId())
4664 .addPerson(person)
4665 .setContentTitle("foo")
4666 .setBubbleMetadata(data)
4667 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4668
4669 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4670 nb.build(), new UserHandle(mUid), null, 0);
4671 // Make sure it has foreground service
4672 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4673 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4674
4675 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4676 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4677 waitForIdle();
4678
4679 // yes person, yes foreground service, BUT NO call, no bubble
4680 assertFalse(mService.getNotificationRecord(
4681 sbn.getKey()).getNotification().isBubbleNotification());
4682 }
4683
4684 @Test
4685 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004686 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004687 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004688
Mady Mellorbe797962019-04-01 16:04:24 -07004689 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004690 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004691 // Give it a person
4692 Person person = new Person.Builder()
4693 .setName("bubblebot")
4694 .build();
4695 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004696 Notification.Builder nb = new Notification.Builder(mContext,
4697 mTestNotificationChannel.getId())
4698 .setContentTitle("foo")
4699 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004700 .setStyle(new Notification.MessagingStyle(person)
4701 .setConversationTitle("Bubble Chat")
4702 .addMessage("Hello?",
4703 SystemClock.currentThreadTimeMillis() - 300000, person)
4704 .addMessage("Is it me you're looking for?",
4705 SystemClock.currentThreadTimeMillis(), person)
4706 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004707 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4708
4709 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4710 nb.build(), new UserHandle(mUid), null, 0);
4711 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4712
4713 // Post the notification
4714 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4715 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4716 waitForIdle();
4717
4718 // not allowed, no bubble
4719 assertFalse(mService.getNotificationRecord(
4720 sbn.getKey()).getNotification().isBubbleNotification());
4721 }
4722
4723 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004724 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004725 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004726 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004727
4728 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07004729 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004730
4731 // Post the notification
Mady Mellorbe797962019-04-01 16:04:24 -07004732 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004733 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4734 waitForIdle();
4735
4736 // no bubble metadata, no bubble
4737 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07004738 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004739 }
4740
4741 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004742 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004743 // Bubbles are allowed except on this channel
4744 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004745
Mady Mellorbe797962019-04-01 16:04:24 -07004746 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004747 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004748 // Give it a person
4749 Person person = new Person.Builder()
4750 .setName("bubblebot")
4751 .build();
4752 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004753 Notification.Builder nb = new Notification.Builder(mContext,
4754 mTestNotificationChannel.getId())
4755 .setContentTitle("foo")
4756 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004757 .setStyle(new Notification.MessagingStyle(person)
4758 .setConversationTitle("Bubble Chat")
4759 .addMessage("Hello?",
4760 SystemClock.currentThreadTimeMillis() - 300000, person)
4761 .addMessage("Is it me you're looking for?",
4762 SystemClock.currentThreadTimeMillis(), person)
4763 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004764 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4765
4766 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4767 nb.build(), new UserHandle(mUid), null, 0);
4768 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4769
4770 // Post the notification
4771 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4772 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4773 waitForIdle();
4774
4775 // channel not allowed, no bubble
4776 assertFalse(mService.getNotificationRecord(
4777 sbn.getKey()).getNotification().isBubbleNotification());
4778 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004779
Mady Mellor49b1bf12019-03-29 12:00:02 -07004780 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004781 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004782 // Bubbles are not allowed!
4783 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004784
4785 // Give it bubble metadata
4786 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4787 // Give it a person
4788 Person person = new Person.Builder()
4789 .setName("bubblebot")
4790 .build();
4791 // Make it a phone call
4792 Notification.Builder nb = new Notification.Builder(mContext,
4793 mTestNotificationChannel.getId())
4794 .setCategory(CATEGORY_CALL)
4795 .addPerson(person)
4796 .setContentTitle("foo")
4797 .setBubbleMetadata(data)
4798 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4799
4800 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4801 nb.build(), new UserHandle(mUid), null, 0);
4802 // Make sure it has foreground service
4803 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4804 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4805
4806 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4807 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4808 waitForIdle();
4809
4810 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
4811 assertFalse(mService.getNotificationRecord(
4812 sbn.getKey()).getNotification().isBubbleNotification());
4813 }
4814
4815 @Test
4816 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07004817 // Bubbles are allowed, but not on channel.
4818 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004819
4820 // Give it bubble metadata
4821 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4822 // Give it a person
4823 Person person = new Person.Builder()
4824 .setName("bubblebot")
4825 .build();
4826 // Make it a phone call
4827 Notification.Builder nb = new Notification.Builder(mContext,
4828 mTestNotificationChannel.getId())
4829 .setCategory(CATEGORY_CALL)
4830 .addPerson(person)
4831 .setContentTitle("foo")
4832 .setBubbleMetadata(data)
4833 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4834
4835 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4836 nb.build(), new UserHandle(mUid), null, 0);
4837 // Make sure it has foreground service
4838 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4839 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4840
4841 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4842 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4843 waitForIdle();
4844
4845 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
4846 assertFalse(mService.getNotificationRecord(
4847 sbn.getKey()).getNotification().isBubbleNotification());
4848 }
4849
4850 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07004851 public void testCancelAllNotifications_cancelsBubble() throws Exception {
4852 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
4853 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
4854 mService.addNotification(nr);
4855
4856 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
4857 waitForIdle();
4858
4859 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4860 assertEquals(0, notifs.length);
4861 assertEquals(0, mService.getNotificationRecordCount());
4862 }
4863
4864 @Test
4865 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
4866 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4867 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4868
4869 // Post the notification
4870 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
4871 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
4872 waitForIdle();
4873
4874 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4875 assertEquals(1, notifs.length);
4876 assertEquals(1, mService.getNotificationRecordCount());
4877
4878 mBinderService.cancelNotificationWithTag(PKG, null, nrBubble.sbn.getId(),
4879 nrBubble.sbn.getUserId());
4880 waitForIdle();
4881
4882 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4883 assertEquals(0, notifs2.length);
4884 assertEquals(0, mService.getNotificationRecordCount());
4885 }
4886
4887 @Test
4888 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
4889 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4890 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4891 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4892
4893 mService.addNotification(nrNormal);
4894 mService.addNotification(nrBubble);
4895
4896 mService.getBinderService().cancelNotificationsFromListener(null, null);
4897 waitForIdle();
4898
4899 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4900 assertEquals(1, notifs.length);
4901 assertEquals(1, mService.getNotificationRecordCount());
4902 }
4903
4904 @Test
4905 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
4906 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
4907 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
4908 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
4909
4910 mService.addNotification(nrNormal);
4911 mService.addNotification(nrBubble);
4912
4913 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
4914 mService.getBinderService().cancelNotificationsFromListener(null, keys);
4915 waitForIdle();
4916
4917 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4918 assertEquals(1, notifs.length);
4919 assertEquals(1, mService.getNotificationRecordCount());
4920 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004921
Julia Reynolds4214da92019-04-10 15:04:06 -04004922 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04004923 public void testGetAllowedAssistantAdjustments() throws Exception {
4924 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004925 assertNotNull(capabilities);
4926
4927 for (int i = capabilities.size() - 1; i >= 0; i--) {
4928 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04004929 mBinderService.disallowAssistantAdjustment(capability);
4930 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
4931 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05004932 assertNotNull(currentCapabilities);
4933 assertFalse(currentCapabilities.contains(capability));
4934 }
4935 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004936
Julia Reynolds4214da92019-04-10 15:04:06 -04004937 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004938 public void testAdjustRestrictedKey() throws Exception {
4939 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04004940 mService.addNotification(r);
4941 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04004942
4943 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
4944 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
4945
4946 Bundle signals = new Bundle();
4947 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
4948 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
4949 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
4950 "", r.getUser().getIdentifier());
4951
4952 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
4953 r.applyAdjustments();
4954
4955 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
4956 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
4957 }
Julia Reynolds657d1642019-03-27 12:15:57 -04004958
Julia Reynolds4214da92019-04-10 15:04:06 -04004959 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004960 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04004961 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
4962 .thenReturn(true);
4963 mService.setZenHelper(mock(ZenModeHelper.class));
4964 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004965 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
4966 boolean isEnabled = true;
4967 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4968 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4969
4970 try {
4971 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04004972 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04004973 } catch (IllegalArgumentException e) {
4974 // yay
4975 }
4976
4977 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4978 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
4979 mBinderService.addAutomaticZenRule(rule);
4980
4981 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
4982 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
4983 mBinderService.addAutomaticZenRule(rule);
4984 }
4985
Julia Reynolds4214da92019-04-10 15:04:06 -04004986 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04004987 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
4988 try {
4989 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
4990 mUid + UserHandle.PER_USER_RANGE);
4991 fail("Cannot call cross user without permission");
4992 } catch (SecurityException e) {
4993 // pass
4994 }
4995
4996 // cross user, with permission, no problem
4997 TestablePermissions perms = mContext.getTestablePermissions();
4998 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4999 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5000 mUid + UserHandle.PER_USER_RANGE);
5001 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005002
Julia Reynolds4214da92019-04-10 15:04:06 -04005003 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005004 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5005 try {
5006 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5007 mUid + UserHandle.PER_USER_RANGE);
5008 fail("Cannot call cross user without permission");
5009 } catch (SecurityException e) {
5010 // pass
5011 }
5012
5013 // cross user, with permission, no problem
5014 TestablePermissions perms = mContext.getTestablePermissions();
5015 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5016 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5017 mUid + UserHandle.PER_USER_RANGE);
5018 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005019
5020 @Test
5021 public void testNotificationBubbleChanged_false() throws Exception {
5022 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005023 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005024
5025 // Notif with bubble metadata but not our other misc requirements
5026 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5027 null /* tvExtender */, true /* isBubble */);
5028
5029 // Say we're foreground
5030 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5031 IMPORTANCE_FOREGROUND);
5032
5033 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5034 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5035 waitForIdle();
5036
Mady Mellor66efd5e2019-05-15 13:38:11 -07005037 // Reset as this is called when the notif is first sent
5038 reset(mListeners);
5039
Mady Mellora54e9fa2019-04-18 13:26:18 -07005040 // First we were a bubble
5041 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5042 assertEquals(1, notifsBefore.length);
5043 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5044
5045 // Notify we're not a bubble
5046 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5047 waitForIdle();
5048
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005049 // Make sure we are not a bubble
5050 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5051 assertEquals(1, notifsAfter.length);
5052 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005053 }
5054
5055 @Test
5056 public void testNotificationBubbleChanged_true() throws Exception {
5057 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005058 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005059
5060 // Plain notification that has bubble metadata
5061 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5062 null /* tvExtender */, true /* isBubble */);
5063 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5064 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5065 waitForIdle();
5066
5067 // Would be a normal notification because wouldn't have met requirements to bubble
5068 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5069 assertEquals(1, notifsBefore.length);
5070 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5071
5072 // Make the package foreground so that we're allowed to be a bubble
5073 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5074 IMPORTANCE_FOREGROUND);
5075
Mady Mellor66efd5e2019-05-15 13:38:11 -07005076 // Reset as this is called when the notif is first sent
5077 reset(mListeners);
5078
Mady Mellora54e9fa2019-04-18 13:26:18 -07005079 // Notify we are now a bubble
5080 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5081 waitForIdle();
5082
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005083 // Make sure we are a bubble
5084 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5085 assertEquals(1, notifsAfter.length);
5086 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005087 }
5088
5089 @Test
5090 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5091 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005092 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005093
5094 // Notif that is not a bubble
5095 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5096 null /* tvExtender */, true /* isBubble */);
5097 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5098 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5099 waitForIdle();
5100
Mady Mellor66efd5e2019-05-15 13:38:11 -07005101 // Reset as this is called when the notif is first sent
5102 reset(mListeners);
5103
Mady Mellora54e9fa2019-04-18 13:26:18 -07005104 // Would be a normal notification because wouldn't have met requirements to bubble
5105 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5106 assertEquals(1, notifsBefore.length);
5107 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5108
5109 // Notify we are now a bubble
5110 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5111 waitForIdle();
5112
5113 // We still wouldn't be a bubble because the notification didn't meet requirements
5114 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5115 assertEquals(1, notifsAfter.length);
5116 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5117 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005118
5119 @Test
5120 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5121 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005122 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005123
5124 // Plain notification that has bubble metadata
5125 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5126 null /* tvExtender */, true /* isBubble */);
5127 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5128 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5129 waitForIdle();
5130
5131 // Would be a normal notification because wouldn't have met requirements to bubble
5132 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5133 assertEquals(1, notifsBefore.length);
5134 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5135
5136 // Make the package foreground so that we're allowed to be a bubble
5137 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5138 IMPORTANCE_FOREGROUND);
5139
5140 // And we are low ram
5141 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5142
5143 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5144 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5145 assertEquals(1, notifsAfter.length);
5146 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005147 }
Mady Mellora7731962019-06-17 17:57:02 -07005148
5149 @Test
5150 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
5151 throws Exception {
5152 // Bubbles are allowed!
5153 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5154
5155 // Give it bubble metadata
5156 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5157 .setSuppressNotification(true)
5158 .setAutoExpandBubble(true).build();
5159 // Give it a person
5160 Person person = new Person.Builder()
5161 .setName("bubblebot")
5162 .build();
5163 // It needs remote input to be bubble-able
5164 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5165 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5166 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5167 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5168 inputIntent).addRemoteInput(remoteInput)
5169 .build();
5170 // Make it messaging style
5171 Notification.Builder nb = new Notification.Builder(mContext,
5172 mTestNotificationChannel.getId())
5173 .setContentTitle("foo")
5174 .setBubbleMetadata(data)
5175 .setStyle(new Notification.MessagingStyle(person)
5176 .setConversationTitle("Bubble Chat")
5177 .addMessage("Hello?",
5178 SystemClock.currentThreadTimeMillis() - 300000, person)
5179 .addMessage("Is it me you're looking for?",
5180 SystemClock.currentThreadTimeMillis(), person)
5181 )
5182 .setActions(replyAction)
5183 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5184
5185 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5186 nb.build(), new UserHandle(mUid), null, 0);
5187 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5188
5189 // Ensure we're not foreground
5190 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5191 IMPORTANCE_VISIBLE);
5192
5193 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5194 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5195 waitForIdle();
5196
5197 // yes allowed, yes messaging, yes bubble
5198 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5199 assertTrue(notif.isBubbleNotification());
5200
5201 // Our flags should have failed since we're not foreground
5202 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
5203 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
5204 }
5205
5206 @Test
5207 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
5208 throws RemoteException {
5209 // Bubbles are allowed!
5210 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5211
5212 // Give it bubble metadata
5213 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5214 .setSuppressNotification(true)
5215 .setAutoExpandBubble(true).build();
5216 // Give it a person
5217 Person person = new Person.Builder()
5218 .setName("bubblebot")
5219 .build();
5220 // It needs remote input to be bubble-able
5221 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5222 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5223 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5224 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5225 inputIntent).addRemoteInput(remoteInput)
5226 .build();
5227 // Make it messaging style
5228 Notification.Builder nb = new Notification.Builder(mContext,
5229 mTestNotificationChannel.getId())
5230 .setContentTitle("foo")
5231 .setBubbleMetadata(data)
5232 .setStyle(new Notification.MessagingStyle(person)
5233 .setConversationTitle("Bubble Chat")
5234 .addMessage("Hello?",
5235 SystemClock.currentThreadTimeMillis() - 300000, person)
5236 .addMessage("Is it me you're looking for?",
5237 SystemClock.currentThreadTimeMillis(), person)
5238 )
5239 .setActions(replyAction)
5240 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5241
5242 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5243 nb.build(), new UserHandle(mUid), null, 0);
5244 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5245
5246 // Ensure we are in the foreground
5247 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5248 IMPORTANCE_FOREGROUND);
5249
5250 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5251 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5252 waitForIdle();
5253
5254 // yes allowed, yes messaging, yes bubble
5255 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5256 assertTrue(notif.isBubbleNotification());
5257
5258 // Our flags should have failed since we are foreground
5259 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
5260 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
5261 }
Mady Mellor22f2f072019-04-18 13:26:18 -07005262
5263 @Test
5264 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
5265 throws Exception {
5266 // Bubbles are allowed!
5267 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5268
5269 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5270 true /* summaryAutoCancel */);
5271
5272 // Dismiss summary
5273 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5274 true);
5275 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(),
5276 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(),
5277 NotificationStats.DISMISSAL_SHADE,
5278 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
5279 waitForIdle();
5280
5281 // The bubble should still exist
5282 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5283 assertEquals(1, notifsAfter.length);
5284 }
5285
5286 @Test
5287 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
5288 throws Exception {
5289 // Bubbles are allowed!
5290 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5291
5292 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5293 true /* summaryAutoCancel */);
5294
5295 // Click summary
5296 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5297 true);
5298 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
5299 nrSummary.getKey(), nv);
5300 waitForIdle();
5301
5302 // The bubble should still exist
5303 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5304 assertEquals(1, notifsAfter.length);
5305 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005306}