blob: 21de668e10c3a8b732cee062915bfa8cb4715924 [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 Reynolds57a974b2019-10-07 11:51:47 -040047import static android.os.UserHandle.USER_SYSTEM;
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -040048import static android.service.notification.Adjustment.KEY_IMPORTANCE;
49import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
Tony Makeda84a72018-11-19 17:01:32 +000050import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
51import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040052
Geoffrey Pitsch03533712017-01-05 10:30:07 -050053import static junit.framework.Assert.assertEquals;
Julia Reynolds727a7282017-04-13 10:54:01 -040054import static junit.framework.Assert.assertFalse;
Julia Reynolds92febc32017-10-26 11:30:31 -040055import static junit.framework.Assert.assertNotNull;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040056import static junit.framework.Assert.assertNull;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050057import static junit.framework.Assert.assertTrue;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050058import static junit.framework.Assert.fail;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050059
Jay Aliomerfea80252019-11-20 18:14:24 -050060import static org.mockito.ArgumentMatchers.isNull;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -050061import static org.mockito.Matchers.anyBoolean;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -040062import static org.mockito.Matchers.anyLong;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050063import static org.mockito.Matchers.anyString;
64import static org.mockito.Matchers.eq;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050065import static org.mockito.Mockito.any;
66import static org.mockito.Mockito.anyInt;
Julia Reynoldsb6c83742019-07-30 18:03:40 -040067import static org.mockito.Mockito.clearInvocations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040068import static org.mockito.Mockito.doAnswer;
Julia Reynolds4afe2642019-05-01 08:42:24 -040069import static org.mockito.Mockito.doNothing;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050070import static org.mockito.Mockito.mock;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040071import static org.mockito.Mockito.never;
72import static org.mockito.Mockito.reset;
Julia Reynolds503ed942017-10-04 16:04:56 -040073import static org.mockito.Mockito.spy;
74import static org.mockito.Mockito.timeout;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050075import static org.mockito.Mockito.times;
76import static org.mockito.Mockito.verify;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050077import static org.mockito.Mockito.when;
78
Julia Reynolds68263d12017-06-21 14:21:19 -040079import android.app.ActivityManager;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -040080import android.app.AppOpsManager;
Julia Reynoldsa94365d2019-04-09 10:48:43 -040081import android.app.AutomaticZenRule;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040082import android.app.IActivityManager;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050083import android.app.INotificationManager;
Julia Reynolds268647a2018-10-25 16:54:27 -040084import android.app.ITransientNotification;
85import android.app.IUriGrantsManager;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050086import android.app.Notification;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040087import android.app.Notification.MessagingStyle.Message;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050088import android.app.NotificationChannel;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040089import android.app.NotificationChannelGroup;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050090import android.app.NotificationManager;
Mady Mellor7eb18ef2019-03-27 14:03:46 -070091import android.app.PendingIntent;
Mady Mellorbe797962019-04-01 16:04:24 -070092import android.app.Person;
Mady Mellora10448e2019-04-26 13:50:58 -070093import android.app.RemoteInput;
Jason Parks50322ff2018-03-27 10:23:33 -050094import android.app.admin.DevicePolicyManagerInternal;
Julia Reynolds7217dc92018-03-07 12:12:09 -050095import android.app.usage.UsageStatsManagerInternal;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040096import android.companion.ICompanionDeviceManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -050097import android.content.ComponentName;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -060098import android.content.ContentUris;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050099import android.content.Context;
Beverlyd4f96492017-08-02 13:36:11 -0400100import android.content.Intent;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500101import android.content.pm.ApplicationInfo;
102import android.content.pm.IPackageManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500103import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500104import android.content.pm.ParceledListSlice;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400105import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200106import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400107import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700108import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400109import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400110import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500111import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400112import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400113import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400114import android.os.IBinder;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400115import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400116import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700117import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500118import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400119import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000120import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600121import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000122import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400123import android.service.notification.Adjustment;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400124import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400125import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500126import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400127import android.service.notification.ZenPolicy;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400128import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400129import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400130import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400131import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400132import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400133import android.testing.TestablePermissions;
Julia Reynolds57a974b2019-10-07 11:51:47 -0400134import android.testing.TestableResources;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400135import android.text.Html;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400136import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000137import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400138import android.util.AtomicFile;
Julia Reynolds469144c2019-06-21 14:30:28 -0400139import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400140import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400141
Mady Mellor49b1bf12019-03-29 12:00:02 -0700142import androidx.annotation.Nullable;
143import androidx.test.InstrumentationRegistry;
144
Kristian Monsen05f34792018-04-09 10:27:16 +0200145import com.android.internal.R;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000146import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Julia Reynolds503ed942017-10-04 16:04:56 -0400147import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400148import com.android.internal.util.FastXmlSerializer;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700149import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400150import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500151import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400152import com.android.server.lights.Light;
153import com.android.server.lights.LightsManager;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400154import com.android.server.notification.NotificationManagerService.NotificationAssistants;
155import com.android.server.notification.NotificationManagerService.NotificationListeners;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700156import com.android.server.uri.UriGrantsManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400157import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400158
159import org.junit.After;
160import org.junit.Before;
161import org.junit.Test;
162import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500163import org.mockito.ArgumentCaptor;
164import org.mockito.Mock;
165import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400166import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400167import org.xmlpull.v1.XmlPullParser;
168import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500169
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400170import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400171import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400172import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400173import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400174import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400175import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400176import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500177import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000178import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400179import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400180import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200181import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500182
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400183
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400184@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400185@RunWith(AndroidTestingRunner.class)
186@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500187public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500188 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000189
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400190 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500191 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500192 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400193 private NotificationManagerInternal mInternalService;
Julia Reynoldsda781472017-04-12 09:41:16 -0400194 @Mock
195 private IPackageManager mPackageManager;
196 @Mock
197 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400198 @Mock
199 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400200 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500201 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400202 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400203 @Mock
204 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400205 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400206 AtomicFile mPolicyFile;
207 File mFile;
208 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400209 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400210 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400211 private UsageStatsManagerInternal mAppUsageStats;
212 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400213 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400214 @Mock
215 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200216 @Mock
217 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400218 @Mock
219 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400220
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500221 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500222 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000223
224 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
225
Julia Reynoldsda781472017-04-12 09:41:16 -0400226 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400227 private NotificationListeners mListeners;
228 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400229 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400230 private ManagedServices.ManagedServiceInfo mListener;
231 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400232 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400233 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400234 @Mock
235 IBinder mPermOwner;
236 @Mock
237 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700238 @Mock
239 IUriGrantsManager mUgm;
240 @Mock
241 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400242 @Mock
243 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000244 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000245 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
246 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400247 @Mock
248 UserManager mUm;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500249
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400250 // Use a Testable subclass so we can simulate calls from the system without failing.
251 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500252 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700253 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000254 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000255 @Nullable
256 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500257
Julia Reynolds0c245002019-03-27 16:10:11 -0400258 TestableNotificationManagerService(Context context) {
Amith Yamasani803eab692017-11-09 17:47:04 -0800259 super(context);
260 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400261
262 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400263 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500264 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700265 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400266 }
267
268 @Override
269 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500270 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700271 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400272 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400273
274 @Override
275 protected ICompanionDeviceManager getCompanionManager() {
276 return null;
277 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800278
279 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800280 protected void reportUserInteraction(NotificationRecord r) {
281 return;
282 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500283
284 @Override
285 protected void handleSavePolicyFile() {
286 return;
287 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000288
289 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000290 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
291 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000292 countLogSmartSuggestionsVisible++;
293 }
294
Annie Meng8b646fd2019-02-01 18:46:42 +0000295 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000296 protected void setNotificationAssistantAccessGrantedForUserInternal(
297 ComponentName assistant, int userId, boolean granted) {
298 if (mNotificationAssistantAccessGrantedCallback != null) {
299 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
300 return;
301 }
302 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
303 }
304
305 private void setNotificationAssistantAccessGrantedCallback(
306 @Nullable NotificationAssistantAccessGrantedCallback callback) {
307 this.mNotificationAssistantAccessGrantedCallback = callback;
308 }
309
310 interface NotificationAssistantAccessGrantedCallback {
311 void onGranted(ComponentName assistant, int userId, boolean granted);
312 }
313
Mady Mellorca0c24c2019-05-16 16:14:32 -0700314 @Override
315 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
316 String packageName) {
317 // Tests for this not being true are in CTS NotificationManagerTest
318 return true;
319 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400320 }
321
Beverly58b24532018-10-02 09:08:23 -0400322 private class TestableToastCallback extends ITransientNotification.Stub {
323 @Override
324 public void show(IBinder windowToken) {
325 }
326
327 @Override
328 public void hide() {
329 }
330 }
331
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500332 @Before
333 public void setUp() throws Exception {
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000334 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
335 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
336
Julia Reynoldsda781472017-04-12 09:41:16 -0400337 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400338
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700339 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
340 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400341 LocalServices.removeServiceForTest(WindowManagerInternal.class);
342 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700343
Julia Reynolds4afe2642019-05-01 08:42:24 -0400344 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
345
Julia Reynolds0c245002019-03-27 16:10:11 -0400346 mService = new TestableNotificationManagerService(mContext);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500347
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400348 // Use this testable looper.
349 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500350 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400351 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400352
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400353 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400354 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
355 Object[] args = invocation.getArguments();
356 return getApplicationInfo((String) args[0], mUid);
357 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500358 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400359 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
360 Object[] args = invocation.getArguments();
361 return getApplicationInfo((String) args[0], mUid);
362 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400363 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500364 final LightsManager mockLightsManager = mock(LightsManager.class);
365 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400366 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400367 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700368 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400369 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400370 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400371 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500372
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400373 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400374 mFile = new File(mContext.getCacheDir(), "test.xml");
375 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400376 final String preupgradeXml = "<notification-policy></notification-policy>";
377 mPolicyFile = new AtomicFile(mFile);
378 FileOutputStream fos = mPolicyFile.startWrite();
379 fos.write(preupgradeXml.getBytes());
380 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400381
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400382 // Setup managed services
383 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400384 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400385 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
386 ArraySet<ComponentName> components = new ArraySet<>();
387 components.add(defaultComponent);
388 when(mListeners.getDefaultComponents()).thenReturn(components);
389 when(mConditionProviders.getDefaultPackages())
390 .thenReturn(new ArraySet<>(Arrays.asList("config")));
391 when(mAssistants.getDefaultComponents()).thenReturn(components);
392 when(mAssistants.queryPackageForServices(
393 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400394 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
395 ManagedServices.Config listenerConfig = new ManagedServices.Config();
396 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
397 when(mListeners.getConfig()).thenReturn(listenerConfig);
398 ManagedServices.Config assistantConfig = new ManagedServices.Config();
399 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
400 when(mAssistants.getConfig()).thenReturn(assistantConfig);
401 ManagedServices.Config dndConfig = new ManagedServices.Config();
402 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
403 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
404
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400405 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
406
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400407 mService.init(mTestableLooper.getLooper(), mRankingHandler,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400408 mPackageManager, mPackageManagerClient, mockLightsManager,
409 mListeners, mAssistants, mConditionProviders,
410 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
411 mGroupHelper, mAm, mAppUsageStats,
412 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
413 mAppOpsManager, mUm);
414 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
415
Julia Reynolds503ed942017-10-04 16:04:56 -0400416 mService.setAudioManager(mAudioManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500417
418 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400419 mBinderService = mService.getBinderService();
420 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500421
422 mBinderService.createNotificationChannels(
423 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400424 assertNotNull(mBinderService.getNotificationChannel(
425 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400426 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500427 }
428
Julia Reynoldsb852e562017-06-06 16:14:18 -0400429 @After
430 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400431 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000432 clearDeviceConfig();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000433 InstrumentationRegistry.getInstrumentation()
434 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400435 }
436
Jay Aliomer4204f252019-08-26 11:36:53 -0400437 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
438 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
439 changed.put(true, new ArrayList<>());
440 changed.put(false, new ArrayList<>());
441 return changed;
442 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400443 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
444 final ApplicationInfo applicationInfo = new ApplicationInfo();
445 applicationInfo.uid = uid;
446 switch (pkg) {
447 case PKG_N_MR1:
448 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
449 break;
450 case PKG_O:
451 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
452 break;
453 case PKG_P:
454 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
455 break;
456 default:
457 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
458 break;
459 }
460 return applicationInfo;
461 }
462
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500463 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400464 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500465 }
466
Mady Mellorc6820342019-05-20 12:04:36 -0700467 private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
468 boolean channelEnabled) {
469 mService.setPreferencesHelper(mPreferencesHelper);
Lyn Han4463f842019-07-09 15:27:28 -0700470 when(mPreferencesHelper.bubblesEnabled()).thenReturn(globalEnabled);
Mady Mellorc6820342019-05-20 12:04:36 -0700471 when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
472 when(mPreferencesHelper.getNotificationChannel(
473 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
474 mTestNotificationChannel);
475 when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
476 mTestNotificationChannel.getImportance());
477 mTestNotificationChannel.setAllowBubbles(channelEnabled);
478 }
479
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500480 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
481 Notification.Builder nb = new Notification.Builder(mContext, "a")
482 .setContentTitle("foo")
483 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400484 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
485 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500486 nb.build(), new UserHandle(userId), null, postTime);
487 return sbn;
488 }
489
Mady Mellor22f2f072019-04-18 13:26:18 -0700490
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400491 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
492 String groupKey, boolean isSummary) {
Mady Mellor22f2f072019-04-18 13:26:18 -0700493 return generateNotificationRecord(channel, id, groupKey, isSummary, false /* isBubble */);
494 }
495
496 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
497 String groupKey, boolean isSummary, boolean isBubble) {
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400498 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
499 .setContentTitle("foo")
500 .setSmallIcon(android.R.drawable.sym_def_app_icon)
501 .setGroup(groupKey)
502 .setGroupSummary(isSummary);
Mady Mellor22f2f072019-04-18 13:26:18 -0700503 if (isBubble) {
504 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
505 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400506
507 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
508 "tag" + System.currentTimeMillis(), mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400509 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000510 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400511 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400512
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500513 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500514 return generateNotificationRecord(channel, null);
515 }
516
517 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
518 Notification.TvExtender extender) {
Mady Mellorbe797962019-04-01 16:04:24 -0700519 return generateNotificationRecord(channel, extender, false /* isBubble */);
520 }
521
522 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
523 Notification.TvExtender extender, boolean isBubble) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500524 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500525 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500526 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500527 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500528 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500529 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500530 if (extender != null) {
531 nb.extend(extender);
532 }
Mady Mellorbe797962019-04-01 16:04:24 -0700533 if (isBubble) {
534 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
535 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400536 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400537 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000538 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500539 }
540
Aran Inkfd2bfd32019-10-04 16:30:01 -0400541 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
542 if (channel == null) {
543 channel = mTestNotificationChannel;
544 }
545 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
546 .setContentTitle("foo")
547 .setSmallIcon(android.R.drawable.sym_def_app_icon);
548 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
549 nb.build(), new UserHandle(userId), null, 0);
550 return new NotificationRecord(mContext, sbn, channel);
551 }
552
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400553 private Map<String, Answer> getSignalExtractorSideEffects() {
554 Map<String, Answer> answers = new ArrayMap<>();
555
556 answers.put("override group key", invocationOnMock -> {
557 ((NotificationRecord) invocationOnMock.getArguments()[0])
558 .setOverrideGroupKey("bananas");
559 return null;
560 });
561 answers.put("override people", invocationOnMock -> {
562 ((NotificationRecord) invocationOnMock.getArguments()[0])
563 .setPeopleOverride(new ArrayList<>());
564 return null;
565 });
566 answers.put("snooze criteria", invocationOnMock -> {
567 ((NotificationRecord) invocationOnMock.getArguments()[0])
568 .setSnoozeCriteria(new ArrayList<>());
569 return null;
570 });
571 answers.put("notification channel", invocationOnMock -> {
572 ((NotificationRecord) invocationOnMock.getArguments()[0])
573 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
574 return null;
575 });
576 answers.put("badging", invocationOnMock -> {
577 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
578 r.setShowBadge(!r.canShowBadge());
579 return null;
580 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500581 answers.put("bubbles", invocationOnMock -> {
582 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
583 r.setAllowBubble(!r.canBubble());
584 return null;
585 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400586 answers.put("package visibility", invocationOnMock -> {
587 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
588 Notification.VISIBILITY_SECRET);
589 return null;
590 });
591
592 return answers;
593 }
594
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400595 private void clearDeviceConfig() {
596 DeviceConfig.resetToDefaults(
597 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
598 }
599
600 private void setDefaultAssistantInDeviceConfig(String componentName) {
601 DeviceConfig.setProperty(
602 DeviceConfig.NAMESPACE_SYSTEMUI,
603 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
604 componentName,
605 false);
606 }
607
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700608 private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() {
609 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
610 return new Notification.BubbleMetadata.Builder()
611 .setIntent(pi)
612 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
613 }
614
Mady Mellor22f2f072019-04-18 13:26:18 -0700615 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
616 throws RemoteException {
617
618 // Notification that has bubble metadata
619 NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel, 1,
620 "BUBBLE_GROUP", false /* isSummary */, true /* isBubble */);
621
622 // Make the package foreground so that we're allowed to be a bubble
623 when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn(
624 IMPORTANCE_FOREGROUND);
625
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400626 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700627 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
628 waitForIdle();
629
630 // Make sure we are a bubble
631 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
632 assertEquals(1, notifsAfter.length);
633 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
634
635 // Plain notification without bubble metadata
636 NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2,
637 "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400638 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700639 nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId());
640 waitForIdle();
641
642 notifsAfter = mBinderService.getActiveNotifications(PKG);
643 assertEquals(2, notifsAfter.length);
644
645 // Summary notification for both of those
646 NotificationRecord nrSummary = generateNotificationRecord(mTestNotificationChannel, 3,
647 "BUBBLE_GROUP", true /* isSummary */, false /* isBubble */);
648 if (summaryAutoCancel) {
649 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
650 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400651 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700652 nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId());
653 waitForIdle();
654
655 notifsAfter = mBinderService.getActiveNotifications(PKG);
656 assertEquals(3, notifsAfter.length);
657
658 return nrSummary;
659 }
660
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500661 @Test
Jay Aliomerfea80252019-11-20 18:14:24 -0500662 public void testDefaultAssistant_overrideDefault() {
663 final int userId = 0;
664 final String testComponent = "package/class";
665 final List<UserInfo> userInfos = new ArrayList<>();
666 userInfos.add(new UserInfo(0, "", 0));
667 final ArraySet<ComponentName> validAssistants = new ArraySet<>();
668 validAssistants.add(ComponentName.unflattenFromString(testComponent));
669 final String originalComponent = DeviceConfig.getProperty(
670 DeviceConfig.NAMESPACE_SYSTEMUI,
671 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE
672 );
673 DeviceConfig.setProperty(
674 DeviceConfig.NAMESPACE_SYSTEMUI,
675 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
676 testComponent,
677 false
678 );
679 when(mActivityManager.isLowRamDevice()).thenReturn(false);
680 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
681 .thenReturn(validAssistants);
682 when(mAssistants.getDefaultComponents()).thenReturn(new ArraySet<>());
683 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
684
685 mService.setDefaultAssistantForUser(userId);
686
687 verify(mAssistants).setPackageOrComponentEnabled(
688 eq(testComponent), eq(userId), eq(true), eq(true));
689
690 DeviceConfig.setProperty(
691 DeviceConfig.NAMESPACE_SYSTEMUI,
692 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
693 originalComponent,
694 false
695 );
696 }
697
698 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500699 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500700 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500701 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400702 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500703 new ParceledListSlice(Arrays.asList(channel)));
704 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400705 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500706 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500707 }
708
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500709 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500710 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500711 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400712 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200713 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500714 fail("Exception should be thrown immediately.");
715 } catch (NullPointerException e) {
716 // pass
717 }
718 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500719
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500720 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500721 public void testCreateNotificationChannels_TwoChannels() throws Exception {
722 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500723 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500724 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500725 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400726 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500727 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400728 assertTrue(mBinderService.getNotificationChannel(
729 PKG, mContext.getUserId(), PKG, "id1") != null);
730 assertTrue(mBinderService.getNotificationChannel(
731 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500732 }
733
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500734 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400735 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
736 throws Exception {
737 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500738 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400739 mBinderService.createNotificationChannels(PKG,
740 new ParceledListSlice(Arrays.asList(channel)));
741
742 // Recreating the channel doesn't throw, but ignores importance.
743 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400744 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400745 mBinderService.createNotificationChannels(PKG,
746 new ParceledListSlice(Arrays.asList(dupeChannel)));
747 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400748 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500749 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400750 }
751
752 @Test
753 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
754 throws Exception {
755 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500756 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400757 mBinderService.createNotificationChannels(PKG,
758 new ParceledListSlice(Arrays.asList(channel)));
759
760 // Recreating with a lower importance is allowed to modify the channel.
761 final NotificationChannel dupeChannel =
762 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
763 mBinderService.createNotificationChannels(PKG,
764 new ParceledListSlice(Arrays.asList(dupeChannel)));
765 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400766 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400767 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
768 }
769
770 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400771 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
772 throws Exception {
773 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500774 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400775 mBinderService.createNotificationChannels(PKG,
776 new ParceledListSlice(Arrays.asList(channel)));
777
778 // The user modifies importance directly, can no longer be changed by the app.
779 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400780 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400781 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
782
783 // Recreating with a lower importance leaves channel unchanged.
784 final NotificationChannel dupeChannel =
785 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
786 mBinderService.createNotificationChannels(PKG,
787 new ParceledListSlice(Arrays.asList(dupeChannel)));
788 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400789 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400790 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400791 }
792
793 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500794 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
795 throws Exception {
796 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500797 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500798 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400799 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400800 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500801 new ParceledListSlice(Arrays.asList(channel1, channel2)));
802 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400803 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500804 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500805 }
806
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500807 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500808 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500809 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
810
811 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400812 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500813 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400814
815 // isBlocked is only used for user blocking, not app suspension
816 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500817 }
818
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500819 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500820 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500821 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
822
823 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400824 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500825 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400826 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400827 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400828
829 mBinderService.createNotificationChannels(
830 PKG, new ParceledListSlice(Arrays.asList(channel)));
831 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400832 mBinderService.enqueueNotificationWithTag(PKG, PKG,
833 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400834 sbn.getId(), sbn.getNotification(), sbn.getUserId());
835 waitForIdle();
836 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
837 }
838
839 @Test
840 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
841 throws Exception {
842 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
843
844 NotificationChannel channel = new NotificationChannel("blocked", "name",
845 NotificationManager.IMPORTANCE_NONE);
846 mBinderService.createNotificationChannels(
847 PKG, new ParceledListSlice(Arrays.asList(channel)));
848
849 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400850 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400851 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400852 sbn.getId(), sbn.getNotification(), sbn.getUserId());
853 waitForIdle();
854 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
855 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400856 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400857 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
858 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400859 }
860
861 @Test
862 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
863 throws Exception {
864 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
865
866 NotificationChannel channel =
867 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
868 mBinderService.createNotificationChannels(
869 PKG, new ParceledListSlice(Arrays.asList(channel)));
870
871 NotificationChannel update =
872 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
873 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
874 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400875 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
876 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400877
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700878 StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400879 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400880 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400881 sbn.getId(), sbn.getNotification(), sbn.getUserId());
882 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700883 // The first time a foreground service notification is shown, we allow the channel
884 // to be updated to allow it to be seen.
885 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
886 assertEquals(IMPORTANCE_LOW,
887 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400888 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
889 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400890 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700891 waitForIdle();
892
893 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
894 update.setFgServiceShown(true);
895 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
896 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400897 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
898 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700899
900 sbn = generateNotificationRecord(channel).sbn;
901 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400902 mBinderService.enqueueNotificationWithTag(PKG, PKG,
903 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700904 sbn.getId(), sbn.getNotification(), sbn.getUserId());
905 waitForIdle();
906 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400907 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400908 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400909 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
910 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500911 }
912
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500913 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -0400914 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
915 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400916 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400917 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
918 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400919
920 NotificationChannel channel = new NotificationChannel("id", "name",
921 NotificationManager.IMPORTANCE_HIGH);
922 channel.setGroup("something");
923 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400924 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -0400925 verify(mUsageStats, times(1)).registerBlocked(eq(r));
926 }
927
928 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -0400929 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500930 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
931
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400932 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -0400933
934 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400935 mBinderService.enqueueNotificationWithTag(PKG, PKG,
936 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -0400937 sbn.getId(), sbn.getNotification(), sbn.getUserId());
938 waitForIdle();
939 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500940 }
941
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500942 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400943 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
944 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
945
946 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
947
948 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400949 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400950 mBinderService.enqueueNotificationWithTag(PKG, PKG,
951 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400952 sbn.getId(), sbn.getNotification(), sbn.getUserId());
953 waitForIdle();
954 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400955 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400956 }
957
Brad Stenning8c991ea2018-07-31 13:33:01 -0700958 /**
959 * Confirm the system user on automotive devices can use car categories
960 */
961 @Test
962 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
963 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
964 .thenReturn(true);
965 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
966 Notification.CATEGORY_CAR_WARNING,
967 Notification.CATEGORY_CAR_INFORMATION);
968 int id = 0;
969 for (String category: categories) {
970 final StatusBarNotification sbn =
971 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
972 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400973 mBinderService.enqueueNotificationWithTag(PKG, PKG,
974 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700975 sbn.getId(), sbn.getNotification(), sbn.getUserId());
976 }
977 waitForIdle();
978 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
979 }
980
981
982 /**
983 * Confirm restricted notification categories only apply to automotive.
984 */
985 @Test
986 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
987 mService.isSystemUid = false;
988 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
989 .thenReturn(false);
990 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
991 Notification.CATEGORY_CAR_WARNING,
992 Notification.CATEGORY_CAR_INFORMATION);
993 int id = 0;
994 for (String category: categories) {
995 final StatusBarNotification sbn =
996 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
997 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400998 mBinderService.enqueueNotificationWithTag(PKG, PKG,
999 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001000 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1001 }
1002 waitForIdle();
1003 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1004 }
1005
1006 /**
1007 * Confirm if a non-system user tries to use the car categories on a automotive device that
1008 * they will get a security exception
1009 */
1010 @Test
1011 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1012 mService.isSystemUid = false;
1013 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1014 .thenReturn(true);
1015 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1016 Notification.CATEGORY_CAR_WARNING,
1017 Notification.CATEGORY_CAR_INFORMATION);
1018 for (String category: categories) {
1019 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1020 sbn.getNotification().category = category;
1021 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001022 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1023 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001024 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1025 fail("Calls from non system apps should not allow use of restricted categories");
1026 } catch (SecurityException e) {
1027 // pass
1028 }
1029 }
1030 waitForIdle();
1031 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1032 }
1033
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001034 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001035 public void testBlockedNotifications_blockedByAssistant() throws Exception {
1036 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001037 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001038
1039 NotificationChannel channel = new NotificationChannel("id", "name",
1040 NotificationManager.IMPORTANCE_HIGH);
1041 NotificationRecord r = generateNotificationRecord(channel);
1042 mService.addEnqueuedNotification(r);
1043
Julia Reynolds27c0a962018-12-10 12:37:28 -05001044 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001045 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001046 Adjustment adjustment = new Adjustment(
1047 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
1048 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001049
1050 NotificationManagerService.PostNotificationRunnable runnable =
1051 mService.new PostNotificationRunnable(r.getKey());
1052 runnable.run();
1053 waitForIdle();
1054
1055 verify(mUsageStats, never()).registerPostedByApp(any());
1056 }
1057
1058 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001059 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001060 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1061 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001062 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001063 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001064 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001065 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001066 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001067 }
1068
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001069 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001070 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001071 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1072 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001073 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001074 mBinderService.cancelNotificationWithTag(PKG, PKG,
1075 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001076 waitForIdle();
1077 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001078 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001079 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001080 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001081 }
1082
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001083 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001084 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001085 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1086 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001087 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001088 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001089 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1090 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001091 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001092 mBinderService.cancelNotificationWithTag(PKG, PKG,
1093 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001094 waitForIdle();
1095 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001096 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001097 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001098 assertEquals(0, mService.getNotificationRecordCount());
1099 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1100 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1101 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001102 }
1103
1104 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001105 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001106 NotificationRecord r = generateNotificationRecord(null);
1107 final StatusBarNotification sbn = r.sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001108 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1109 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001110 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001111 mBinderService.cancelNotificationsFromListener(null, null);
1112 waitForIdle();
1113 StatusBarNotification[] notifs =
1114 mBinderService.getActiveNotifications(sbn.getPackageName());
1115 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001116 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001117 }
1118
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001119 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001120 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
1121 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001122 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1123 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001124 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001125 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001126 waitForIdle();
1127 StatusBarNotification[] notifs =
1128 mBinderService.getActiveNotifications(sbn.getPackageName());
1129 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001130 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001131 }
1132
1133 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001134 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1135 throws Exception {
1136 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1137 sbn.getNotification().flags =
1138 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1139 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1140 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1141 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1142 waitForIdle();
1143 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1144 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1145 }
1146
1147 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001148 public void testUserInitiatedClearAll_noLeak() throws Exception {
1149 final NotificationRecord n = generateNotificationRecord(
1150 mTestNotificationChannel, 1, "group", true);
1151
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001152 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1153 "testUserInitiatedClearAll_noLeak",
Julia Reynolds080361e2017-07-13 11:23:12 -04001154 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
1155 waitForIdle();
1156
Julia Reynolds503ed942017-10-04 16:04:56 -04001157 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001158 n.getUserId());
1159 waitForIdle();
1160 StatusBarNotification[] notifs =
1161 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1162 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001163 assertEquals(0, mService.getNotificationRecordCount());
1164 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1165 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1166 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001167 }
1168
1169 @Test
1170 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1171 final NotificationRecord parent = generateNotificationRecord(
1172 mTestNotificationChannel, 1, "group1", true);
1173 final NotificationRecord child = generateNotificationRecord(
1174 mTestNotificationChannel, 2, "group1", false);
1175
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001176 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1177 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds080361e2017-07-13 11:23:12 -04001178 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001179 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1180 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds080361e2017-07-13 11:23:12 -04001181 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1182 waitForIdle();
1183
1184 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1185 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001186 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001187 }
1188
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001189 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001190 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1191 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1192 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001193 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1194 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001195 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1196 }
1197 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1198 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001199
Julia Reynolds503ed942017-10-04 16:04:56 -04001200 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001201 }
1202
1203 @Test
1204 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1205 final NotificationRecord parent = generateNotificationRecord(
1206 mTestNotificationChannel, 1, "group1", true);
1207 final NotificationRecord parentAsChild = generateNotificationRecord(
1208 mTestNotificationChannel, 1, "group1", false);
1209 final NotificationRecord child = generateNotificationRecord(
1210 mTestNotificationChannel, 2, "group1", false);
1211
1212 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001213 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1214 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001215 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1216 waitForIdle();
1217
1218 // enqueue the child several times
1219 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001220 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1221 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001222 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1223 }
1224 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001225 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1226 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001227 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1228 parentAsChild.sbn.getUserId());
1229 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001230
Julia Reynolds503ed942017-10-04 16:04:56 -04001231 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001232 }
1233
1234 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001235 public void testAutobundledSummary_notificationAdded() {
1236 NotificationRecord summary =
1237 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1238 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1239 mService.addNotification(summary);
1240 mService.mSummaryByGroupKey.put("pkg", summary);
1241 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1242 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001243 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001244
1245 assertTrue(summary.sbn.isOngoing());
1246 }
1247
1248 @Test
1249 public void testAutobundledSummary_notificationRemoved() {
1250 NotificationRecord summary =
1251 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1252 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1253 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1254 mService.addNotification(summary);
1255 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1256 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1257 mService.mSummaryByGroupKey.put("pkg", summary);
1258
Mady Mellor6d775f82019-11-12 16:12:19 -08001259 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001260
1261 assertFalse(summary.sbn.isOngoing());
1262 }
1263
1264 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001265 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1266 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001267 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001268 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1269 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001270 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001271 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001272 waitForIdle();
1273 StatusBarNotification[] notifs =
1274 mBinderService.getActiveNotifications(sbn.getPackageName());
1275 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001276 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001277 }
1278
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001279 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001280 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1281 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001282 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001283 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1284 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001285 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001286 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1287 waitForIdle();
1288 StatusBarNotification[] notifs =
1289 mBinderService.getActiveNotifications(sbn.getPackageName());
1290 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001291 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001292 }
1293
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001294 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001295 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1296 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001297 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1298 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001299 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001300 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1301 waitForIdle();
1302 StatusBarNotification[] notifs =
1303 mBinderService.getActiveNotifications(sbn.getPackageName());
1304 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001305 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001306 }
1307
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001308 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001309 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1310 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001311 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1312 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001313 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001314 // Null pkg is how we signal a user switch.
1315 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1316 waitForIdle();
1317 StatusBarNotification[] notifs =
1318 mBinderService.getActiveNotifications(sbn.getPackageName());
1319 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001320 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001321 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001322
1323 @Test
Beverly40239d92017-07-07 10:20:41 -04001324 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1325 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1326 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001327 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1328 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001329 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1330 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1331 waitForIdle();
1332 StatusBarNotification[] notifs =
1333 mBinderService.getActiveNotifications(sbn.getPackageName());
1334 assertEquals(0, notifs.length);
1335 }
1336
1337 @Test
1338 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1339 final NotificationRecord notif = generateNotificationRecord(
1340 mTestNotificationChannel, 1, "group", true);
1341 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001342 mService.addNotification(notif);
1343 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001344 notif.getUserId(), 0, null);
1345 waitForIdle();
1346 StatusBarNotification[] notifs =
1347 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1348 assertEquals(0, notifs.length);
1349 }
1350
1351 @Test
1352 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1353 final NotificationRecord notif = generateNotificationRecord(
1354 mTestNotificationChannel, 1, "group", true);
1355 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001356 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001357
Julia Reynolds503ed942017-10-04 16:04:56 -04001358 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001359 notif.getUserId());
1360 waitForIdle();
1361 StatusBarNotification[] notifs =
1362 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1363 assertEquals(1, notifs.length);
1364 }
1365
1366 @Test
1367 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1368 final NotificationRecord parent = generateNotificationRecord(
1369 mTestNotificationChannel, 1, "group", true);
1370 final NotificationRecord child = generateNotificationRecord(
1371 mTestNotificationChannel, 2, "group", false);
1372 final NotificationRecord child2 = generateNotificationRecord(
1373 mTestNotificationChannel, 3, "group", false);
1374 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1375 final NotificationRecord newGroup = generateNotificationRecord(
1376 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001377 mService.addNotification(parent);
1378 mService.addNotification(child);
1379 mService.addNotification(child2);
1380 mService.addNotification(newGroup);
1381 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001382 waitForIdle();
1383 StatusBarNotification[] notifs =
1384 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1385 assertEquals(1, notifs.length);
1386 }
1387
1388 @Test
1389 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1390 final NotificationRecord parent = generateNotificationRecord(
1391 mTestNotificationChannel, 1, "group", true);
1392 final NotificationRecord child = generateNotificationRecord(
1393 mTestNotificationChannel, 2, "group", false);
1394 final NotificationRecord child2 = generateNotificationRecord(
1395 mTestNotificationChannel, 3, "group", false);
1396 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1397 final NotificationRecord newGroup = generateNotificationRecord(
1398 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001399 mService.addNotification(parent);
1400 mService.addNotification(child);
1401 mService.addNotification(child2);
1402 mService.addNotification(newGroup);
1403 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001404 parent.getUserId());
1405 waitForIdle();
1406 StatusBarNotification[] notifs =
1407 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1408 assertEquals(1, notifs.length);
1409 }
1410
1411 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001412 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001413 Notification n =
1414 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1415 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1416 .build();
1417 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
1418 n, new UserHandle(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001419 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001420 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001421 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001422 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1423 sbn.getUserId());
1424 waitForIdle();
1425 StatusBarNotification[] notifs =
1426 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001427 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001428 }
1429
1430 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001431 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1432 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1433 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001434 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001435 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001436 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1437 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001438 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001439 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001440 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1441 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001442 waitForIdle();
1443 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001444 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001445 }
1446
1447 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001448 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1449 throws Exception {
1450 final NotificationRecord parent = generateNotificationRecord(
1451 mTestNotificationChannel, 1, "group", true);
1452 final NotificationRecord child = generateNotificationRecord(
1453 mTestNotificationChannel, 2, "group", false);
1454 final NotificationRecord child2 = generateNotificationRecord(
1455 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001456 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001457 final NotificationRecord newGroup = generateNotificationRecord(
1458 mTestNotificationChannel, 4, "group2", false);
1459 mService.addNotification(parent);
1460 mService.addNotification(child);
1461 mService.addNotification(child2);
1462 mService.addNotification(newGroup);
1463 mService.getBinderService().cancelNotificationsFromListener(null, null);
1464 waitForIdle();
1465 StatusBarNotification[] notifs =
1466 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1467 assertEquals(0, notifs.length);
1468 }
1469
1470 @Test
1471 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1472 throws Exception {
1473 final NotificationRecord parent = generateNotificationRecord(
1474 mTestNotificationChannel, 1, "group", true);
1475 final NotificationRecord child = generateNotificationRecord(
1476 mTestNotificationChannel, 2, "group", false);
1477 final NotificationRecord child2 = generateNotificationRecord(
1478 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001479 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001480 final NotificationRecord newGroup = generateNotificationRecord(
1481 mTestNotificationChannel, 4, "group2", false);
1482 mService.addNotification(parent);
1483 mService.addNotification(child);
1484 mService.addNotification(child2);
1485 mService.addNotification(newGroup);
1486 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1487 child2.sbn.getKey(), newGroup.sbn.getKey()};
1488 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1489 waitForIdle();
1490 StatusBarNotification[] notifs =
1491 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1492 assertEquals(1, notifs.length);
1493 }
1494
1495 @Test
1496 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1497 final NotificationRecord parent = generateNotificationRecord(
1498 mTestNotificationChannel, 1, "group", true);
1499 final NotificationRecord child = generateNotificationRecord(
1500 mTestNotificationChannel, 2, "group", false);
1501 final NotificationRecord child2 = generateNotificationRecord(
1502 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001503 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001504 final NotificationRecord newGroup = generateNotificationRecord(
1505 mTestNotificationChannel, 4, "group2", false);
1506 mService.addNotification(parent);
1507 mService.addNotification(child);
1508 mService.addNotification(child2);
1509 mService.addNotification(newGroup);
1510 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1511 parent.getUserId());
1512 waitForIdle();
1513 StatusBarNotification[] notifs =
1514 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1515 assertEquals(0, notifs.length);
1516 }
1517
1518 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001519 public void testFindGroupNotificationsLocked() throws Exception {
1520 // make sure the same notification can be found in both lists and returned
1521 final NotificationRecord group1 = generateNotificationRecord(
1522 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001523 mService.addEnqueuedNotification(group1);
1524 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001525
1526 // should not be returned
1527 final NotificationRecord group2 = generateNotificationRecord(
1528 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001529 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001530 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1531 waitForIdle();
1532
1533 // should not be returned
1534 final NotificationRecord nonGroup = generateNotificationRecord(
1535 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001536 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001537 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1538 waitForIdle();
1539
1540 // same group, child, should be returned
1541 final NotificationRecord group1Child = generateNotificationRecord(
1542 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001543 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1544 group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001545 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1546 waitForIdle();
1547
1548 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001549 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001550 group1.sbn.getUserId());
1551 assertEquals(3, inGroup1.size());
1552 for (NotificationRecord record : inGroup1) {
1553 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1554 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1555 }
1556 }
1557
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001558 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001559 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1560 final NotificationRecord notif = generateNotificationRecord(
1561 mTestNotificationChannel, 1, "group", true);
1562 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1563 mService.addNotification(notif);
1564 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1565 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1566 waitForIdle();
1567 StatusBarNotification[] notifs =
1568 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1569 assertEquals(0, notifs.length);
1570 }
1571
1572 @Test
1573 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1574 throws Exception {
1575 final NotificationRecord parent = generateNotificationRecord(
1576 mTestNotificationChannel, 1, "group", true);
1577 final NotificationRecord child = generateNotificationRecord(
1578 mTestNotificationChannel, 2, "group", false);
1579 final NotificationRecord child2 = generateNotificationRecord(
1580 mTestNotificationChannel, 3, "group", false);
1581 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1582 final NotificationRecord newGroup = generateNotificationRecord(
1583 mTestNotificationChannel, 4, "group2", false);
1584 mService.addNotification(parent);
1585 mService.addNotification(child);
1586 mService.addNotification(child2);
1587 mService.addNotification(newGroup);
1588 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1589 child2.sbn.getKey(), newGroup.sbn.getKey()};
1590 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1591 waitForIdle();
1592 StatusBarNotification[] notifs =
1593 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1594 assertEquals(0, notifs.length);
1595 }
1596
1597 @Test
1598 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1599 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1600 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001601 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1602 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001603 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1604 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1605 waitForIdle();
1606 StatusBarNotification[] notifs =
1607 mBinderService.getActiveNotifications(sbn.getPackageName());
1608 assertEquals(0, notifs.length);
1609 }
1610
1611 @Test
1612 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1613 final NotificationRecord notif = generateNotificationRecord(
1614 mTestNotificationChannel, 1, "group", true);
1615 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1616 mService.addNotification(notif);
1617 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1618 notif.getUserId(), 0, null);
1619 waitForIdle();
1620 StatusBarNotification[] notifs =
1621 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1622 assertEquals(0, notifs.length);
1623 }
1624
1625 @Test
1626 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1627 final NotificationRecord notif = generateNotificationRecord(
1628 mTestNotificationChannel, 1, "group", true);
1629 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1630 mService.addNotification(notif);
1631
1632 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1633 notif.getUserId());
1634 waitForIdle();
1635 StatusBarNotification[] notifs =
1636 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1637 assertEquals(1, notifs.length);
1638 }
1639
1640 @Test
1641 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1642 final NotificationRecord parent = generateNotificationRecord(
1643 mTestNotificationChannel, 1, "group", true);
1644 final NotificationRecord child = generateNotificationRecord(
1645 mTestNotificationChannel, 2, "group", false);
1646 final NotificationRecord child2 = generateNotificationRecord(
1647 mTestNotificationChannel, 3, "group", false);
1648 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1649 final NotificationRecord newGroup = generateNotificationRecord(
1650 mTestNotificationChannel, 4, "group2", false);
1651 mService.addNotification(parent);
1652 mService.addNotification(child);
1653 mService.addNotification(child2);
1654 mService.addNotification(newGroup);
1655 mService.getBinderService().cancelNotificationsFromListener(null, null);
1656 waitForIdle();
1657 StatusBarNotification[] notifs =
1658 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1659 assertEquals(1, notifs.length);
1660 }
1661
1662 @Test
1663 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1664 throws Exception {
1665 final NotificationRecord parent = generateNotificationRecord(
1666 mTestNotificationChannel, 1, "group", true);
1667 final NotificationRecord child = generateNotificationRecord(
1668 mTestNotificationChannel, 2, "group", false);
1669 final NotificationRecord child2 = generateNotificationRecord(
1670 mTestNotificationChannel, 3, "group", false);
1671 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1672 final NotificationRecord newGroup = generateNotificationRecord(
1673 mTestNotificationChannel, 4, "group2", false);
1674 mService.addNotification(parent);
1675 mService.addNotification(child);
1676 mService.addNotification(child2);
1677 mService.addNotification(newGroup);
1678 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1679 child2.sbn.getKey(), newGroup.sbn.getKey()};
1680 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1681 waitForIdle();
1682 StatusBarNotification[] notifs =
1683 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1684 assertEquals(0, notifs.length);
1685 }
1686
1687 @Test
1688 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1689 final NotificationRecord parent = generateNotificationRecord(
1690 mTestNotificationChannel, 1, "group", true);
1691 final NotificationRecord child = generateNotificationRecord(
1692 mTestNotificationChannel, 2, "group", false);
1693 final NotificationRecord child2 = generateNotificationRecord(
1694 mTestNotificationChannel, 3, "group", false);
1695 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1696 final NotificationRecord newGroup = generateNotificationRecord(
1697 mTestNotificationChannel, 4, "group2", false);
1698 mService.addNotification(parent);
1699 mService.addNotification(child);
1700 mService.addNotification(child2);
1701 mService.addNotification(newGroup);
1702 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1703 parent.getUserId());
1704 waitForIdle();
1705 StatusBarNotification[] notifs =
1706 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1707 assertEquals(1, notifs.length);
1708 }
1709
1710 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001711 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001712 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001713 mService.setPreferencesHelper(mPreferencesHelper);
1714 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001715 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001716 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001717
Julia Reynoldsbad42972017-04-25 13:52:49 -04001718 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001719 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001720 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001721 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001722 anyString(), anyInt(), eq("foo"), anyBoolean());
1723 }
1724
1725 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001726 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001727 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001728 mService.setPreferencesHelper(mPreferencesHelper);
1729 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001730 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001731 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001732
Julia Reynoldsbad42972017-04-25 13:52:49 -04001733 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001734 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
1735 0, generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001736 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001737 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001738 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001739
1740 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001741 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001742 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001743
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001744 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001745 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1746 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1747
1748 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1749 captor.getValue().getAction());
1750 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001751 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1752 }
1753
1754 @Test
1755 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1756 mService.setPreferencesHelper(mPreferencesHelper);
1757
1758 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1759 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001760 }
1761
1762 @Test
1763 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001764 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001765
1766 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1767 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1768 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1769
1770 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1771 captor.getValue().getAction());
1772 assertEquals(PKG, captor.getValue().getPackage());
1773 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1774 }
1775
1776 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001777 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001778 mService.setPreferencesHelper(mPreferencesHelper);
1779 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001780 eq(mTestNotificationChannel.getId()), anyBoolean()))
1781 .thenReturn(mTestNotificationChannel);
1782
1783 NotificationChannel updatedChannel =
1784 new NotificationChannel(mTestNotificationChannel.getId(),
1785 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1786
1787 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1788 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1789 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1790
1791 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1792 captor.getValue().getAction());
1793 assertEquals(PKG, captor.getValue().getPackage());
1794 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001795 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001796 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1797 }
1798
1799 @Test
1800 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1801 NotificationChannel existingChannel =
1802 new NotificationChannel(mTestNotificationChannel.getId(),
1803 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001804 mService.setPreferencesHelper(mPreferencesHelper);
1805 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001806 eq(mTestNotificationChannel.getId()), anyBoolean()))
1807 .thenReturn(existingChannel);
1808
1809 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1810 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1811 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1812
1813 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1814 captor.getValue().getAction());
1815 assertEquals(PKG, captor.getValue().getPackage());
1816 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001817 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001818 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1819 }
1820
1821 @Test
1822 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1823 NotificationChannel existingChannel =
1824 new NotificationChannel(mTestNotificationChannel.getId(),
1825 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001826 mService.setPreferencesHelper(mPreferencesHelper);
1827 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001828 eq(mTestNotificationChannel.getId()), anyBoolean()))
1829 .thenReturn(existingChannel);
1830
1831 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1832 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1833 }
1834
1835 @Test
1836 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1837 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001838 mService.setPreferencesHelper(mPreferencesHelper);
1839 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001840 .thenReturn(existing);
1841
1842 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1843 updated.setBlocked(true);
1844
1845 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1846 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1847 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1848
1849 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1850 captor.getValue().getAction());
1851 assertEquals(PKG, captor.getValue().getPackage());
1852 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001853 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001854 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1855 }
1856
1857 @Test
1858 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1859 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1860 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001861 mService.setPreferencesHelper(mPreferencesHelper);
1862 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001863 .thenReturn(existing);
1864
1865 mBinderService.updateNotificationChannelGroupForPackage(
1866 PKG, 0, new NotificationChannelGroup("id", "name"));
1867 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1868 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1869
1870 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1871 captor.getValue().getAction());
1872 assertEquals(PKG, captor.getValue().getPackage());
1873 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001874 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001875 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1876 }
1877
1878 @Test
1879 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1880 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001881 mService.setPreferencesHelper(mPreferencesHelper);
1882 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001883 .thenReturn(existing);
1884
1885 mBinderService.updateNotificationChannelGroupForPackage(
1886 PKG, 0, new NotificationChannelGroup("id", "new name"));
1887 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1888 }
1889
1890 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001891 public void testCreateChannelNotifyListener() throws Exception {
1892 List<String> associations = new ArrayList<>();
1893 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001894 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001895 mService.setPreferencesHelper(mPreferencesHelper);
1896 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001897 eq(mTestNotificationChannel.getId()), anyBoolean()))
1898 .thenReturn(mTestNotificationChannel);
1899 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001900 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001901 eq(channel2.getId()), anyBoolean()))
1902 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001903 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1904 eq(channel2), anyBoolean(), anyBoolean()))
1905 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001906
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001907 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001908 mBinderService.createNotificationChannels(PKG,
1909 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001910 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001911 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001912 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001913 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001914 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001915 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1916 }
1917
1918 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001919 public void testCreateChannelGroupNotifyListener() throws Exception {
1920 List<String> associations = new ArrayList<>();
1921 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001922 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001923 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001924 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1925 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1926
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001927 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001928 mBinderService.createNotificationChannelGroups(PKG,
1929 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001930 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001931 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001932 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001933 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001934 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001935 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1936 }
1937
1938 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001939 public void testUpdateChannelNotifyListener() throws Exception {
1940 List<String> associations = new ArrayList<>();
1941 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001942 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001943 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001944 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001945 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001946 eq(mTestNotificationChannel.getId()), anyBoolean()))
1947 .thenReturn(mTestNotificationChannel);
1948
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001949 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001950 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001951 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001952 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001953 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1954 }
1955
1956 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001957 public void testDeleteChannelNotifyListener() throws Exception {
1958 List<String> associations = new ArrayList<>();
1959 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001960 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001961 mService.setPreferencesHelper(mPreferencesHelper);
1962 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001963 eq(mTestNotificationChannel.getId()), anyBoolean()))
1964 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001965 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001966 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001967 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001968 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001969 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1970 }
1971
1972 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001973 public void testDeleteChannelGroupNotifyListener() throws Exception {
1974 List<String> associations = new ArrayList<>();
1975 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001976 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001977 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001978 mService.setPreferencesHelper(mPreferencesHelper);
1979 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001980 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001981 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001982 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001983 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001984 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001985 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1986 }
1987
1988 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001989 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001990 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001991 List<String> associations = new ArrayList<>();
1992 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001993 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001994 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001995 eq(mTestNotificationChannel.getId()), anyBoolean()))
1996 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001997
1998 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001999 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002000
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002001 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002002 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002003
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002004 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002005 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002006 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2007 }
2008
2009 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002010 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002011 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002012 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002013 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002014
2015 try {
2016 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002017 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002018 fail("listeners that don't have a companion device shouldn't be able to call this");
2019 } catch (SecurityException e) {
2020 // pass
2021 }
2022
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002023 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002024 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002025
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002026 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002027 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2028 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2029 }
2030
2031 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002032 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002033 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002034 List<String> associations = new ArrayList<>();
2035 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002036 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002037 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002038 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002039 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002040 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002041
2042 try {
2043 mBinderService.updateNotificationChannelFromPrivilegedListener(
2044 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2045 fail("incorrectly allowed a change to a user listener cannot see");
2046 } catch (SecurityException e) {
2047 // pass
2048 }
2049
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002050 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002051 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002052
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002053 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002054 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002055 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2056 }
2057
2058 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002059 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002060 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002061 List<String> associations = new ArrayList<>();
2062 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002063 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002064
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002065 mBinderService.getNotificationChannelsFromPrivilegedListener(
2066 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002067
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002068 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002069 anyString(), anyInt(), anyBoolean());
2070 }
2071
2072 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002073 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002074 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002075 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002076 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002077
2078 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002079 mBinderService.getNotificationChannelsFromPrivilegedListener(
2080 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002081 fail("listeners that don't have a companion device shouldn't be able to call this");
2082 } catch (SecurityException e) {
2083 // pass
2084 }
2085
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002086 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002087 anyString(), anyInt(), anyBoolean());
2088 }
2089
2090 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002091 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2092 throws Exception {
2093 mService.setPreferencesHelper(mPreferencesHelper);
2094 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2095 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2096
2097 mBinderService.getNotificationChannelsFromPrivilegedListener(
2098 null, PKG, Process.myUserHandle());
2099
2100 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2101 anyString(), anyInt(), anyBoolean());
2102 }
2103
2104 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002105 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2106 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002107 mService.setPreferencesHelper(mPreferencesHelper);
2108 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2109 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2110
2111 try {
2112 mBinderService.getNotificationChannelsFromPrivilegedListener(
2113 null, PKG, Process.myUserHandle());
2114 fail("listeners that don't have a companion device shouldn't be able to call this");
2115 } catch (SecurityException e) {
2116 // pass
2117 }
2118
2119 verify(mPreferencesHelper, never()).getNotificationChannels(
2120 anyString(), anyInt(), anyBoolean());
2121 }
2122
2123 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002124 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002125 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002126 List<String> associations = new ArrayList<>();
2127 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002128 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002129 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2130 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002131 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002132
2133 try {
2134 mBinderService.getNotificationChannelsFromPrivilegedListener(
2135 null, PKG, Process.myUserHandle());
2136 fail("listener getting channels from a user they cannot see");
2137 } catch (SecurityException e) {
2138 // pass
2139 }
2140
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002141 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002142 anyString(), anyInt(), anyBoolean());
2143 }
2144
2145 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002146 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002147 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002148 List<String> associations = new ArrayList<>();
2149 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002150 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002151
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002152 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2153 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002154
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002155 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002156 }
2157
2158 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002159 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002160 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002161 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002162 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002163
2164 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002165 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2166 null, PKG, Process.myUserHandle());
2167 fail("listeners that don't have a companion device shouldn't be able to call this");
2168 } catch (SecurityException e) {
2169 // pass
2170 }
2171
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002172 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002173 }
2174
2175 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002176 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002177 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002178 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002179 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002180 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2181 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002182 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002183 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002184 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2185 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002186 fail("listeners that don't have a companion device shouldn't be able to call this");
2187 } catch (SecurityException e) {
2188 // pass
2189 }
2190
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002191 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002192 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002193
2194 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002195 public void testHasCompanionDevice_failure() throws Exception {
2196 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2197 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002198 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002199 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002200
2201 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002202 public void testHasCompanionDevice_noService() {
2203 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04002204
Julia Reynolds503ed942017-10-04 16:04:56 -04002205 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002206 }
2207
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002208 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002209 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2210 final NotificationRecord notification = generateNotificationRecord(
2211 mTestNotificationChannel, 1, null, true);
2212 mService.addNotification(notification);
2213 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2214
2215 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2216 mService.new SnoozeNotificationRunnable(
2217 notification.getKey(), 100, null);
2218 snoozeNotificationRunnable.run();
2219 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2220 mService.new SnoozeNotificationRunnable(
2221 notification.getKey(), 100, null);
2222 snoozeNotificationRunnable.run();
2223
2224 // snooze twice
2225 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2226 }
2227
2228 @Test
2229 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2230 final NotificationRecord notification = generateNotificationRecord(
2231 mTestNotificationChannel, 1, "group", true);
2232 mService.addNotification(notification);
2233 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2234
2235 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2236 mService.new SnoozeNotificationRunnable(
2237 notification.getKey(), 100, null);
2238 snoozeNotificationRunnable.run();
2239 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2240 mService.new SnoozeNotificationRunnable(
2241 notification.getKey(), 100, null);
2242 snoozeNotificationRunnable.run();
2243
2244 // snooze twice
2245 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2246 }
2247
2248 @Test
2249 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2250 final NotificationRecord notification = generateNotificationRecord(
2251 mTestNotificationChannel, 1, "group", true);
2252 final NotificationRecord notification2 = generateNotificationRecord(
2253 mTestNotificationChannel, 2, "group", true);
2254 mService.addNotification(notification);
2255 mService.addNotification(notification2);
2256 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2257 when(mSnoozeHelper.getNotifications(
2258 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2259
2260 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2261 mService.new SnoozeNotificationRunnable(
2262 notification.getKey(), 100, null);
2263 snoozeNotificationRunnable.run();
2264 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2265 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2266 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2267 mService.new SnoozeNotificationRunnable(
2268 notification.getKey(), 100, null);
2269 snoozeNotificationRunnable.run();
2270
2271 // snooze twice
2272 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2273 }
2274
2275 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002276 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2277 final NotificationRecord nonGrouped = generateNotificationRecord(
2278 mTestNotificationChannel, 1, null, false);
2279 final NotificationRecord grouped = generateNotificationRecord(
2280 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002281 mService.addNotification(grouped);
2282 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002283
2284 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002285 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002286 nonGrouped.getKey(), 100, null);
2287 snoozeNotificationRunnable.run();
2288
2289 // only snooze the one notification
2290 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002291 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002292 }
2293
2294 @Test
2295 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2296 final NotificationRecord parent = generateNotificationRecord(
2297 mTestNotificationChannel, 1, "group", true);
2298 final NotificationRecord child = generateNotificationRecord(
2299 mTestNotificationChannel, 2, "group", false);
2300 final NotificationRecord child2 = generateNotificationRecord(
2301 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002302 mService.addNotification(parent);
2303 mService.addNotification(child);
2304 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002305
2306 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002307 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002308 parent.getKey(), 100, null);
2309 snoozeNotificationRunnable.run();
2310
2311 // snooze parent and children
2312 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2313 }
2314
2315 @Test
2316 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2317 final NotificationRecord parent = generateNotificationRecord(
2318 mTestNotificationChannel, 1, "group", true);
2319 final NotificationRecord child = generateNotificationRecord(
2320 mTestNotificationChannel, 2, "group", false);
2321 final NotificationRecord child2 = generateNotificationRecord(
2322 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002323 mService.addNotification(parent);
2324 mService.addNotification(child);
2325 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002326
2327 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002328 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002329 child2.getKey(), 100, null);
2330 snoozeNotificationRunnable.run();
2331
2332 // only snooze the one child
2333 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2334 }
2335
2336 @Test
2337 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2338 final NotificationRecord parent = generateNotificationRecord(
2339 mTestNotificationChannel, 1, "group", true);
2340 assertTrue(parent.sbn.getNotification().isGroupSummary());
2341 final NotificationRecord child = generateNotificationRecord(
2342 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002343 mService.addNotification(parent);
2344 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002345
2346 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002347 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002348 child.getKey(), 100, null);
2349 snoozeNotificationRunnable.run();
2350
2351 // snooze child and summary
2352 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2353 }
2354
2355 @Test
2356 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2357 final NotificationRecord child = generateNotificationRecord(
2358 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002359 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002360
2361 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002362 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002363 child.getKey(), 100, null);
2364 snoozeNotificationRunnable.run();
2365
2366 // snooze child only
2367 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2368 }
2369
2370 @Test
2371 public void testPostGroupChild_unsnoozeParent() throws Exception {
2372 final NotificationRecord child = generateNotificationRecord(
2373 mTestNotificationChannel, 2, "group", false);
2374
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002375 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002376 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2377 waitForIdle();
2378
2379 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2380 anyString(), anyInt(), eq(child.getGroupKey()));
2381 }
2382
2383 @Test
2384 public void testPostNonGroup_noUnsnoozing() throws Exception {
2385 final NotificationRecord record = generateNotificationRecord(
2386 mTestNotificationChannel, 2, null, false);
2387
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002388 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002389 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2390 waitForIdle();
2391
2392 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2393 }
2394
2395 @Test
2396 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2397 final NotificationRecord parent = generateNotificationRecord(
2398 mTestNotificationChannel, 2, "group", true);
2399
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002400 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002401 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2402 waitForIdle();
2403
2404 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2405 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002406
2407 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002408 public void testSetListenerAccessForUser() throws Exception {
2409 UserHandle user = UserHandle.of(10);
2410 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002411 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2412
Julia Reynolds92febc32017-10-26 11:30:31 -04002413
2414 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2415 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2416 c.flattenToString(), user.getIdentifier(), true, true);
2417 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2418 c.flattenToString(), user.getIdentifier(), false, true);
2419 verify(mAssistants, never()).setPackageOrComponentEnabled(
2420 any(), anyInt(), anyBoolean(), anyBoolean());
2421 }
2422
2423 @Test
2424 public void testSetAssistantAccessForUser() throws Exception {
2425 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002426 List<UserInfo> uis = new ArrayList<>();
2427 UserInfo ui = new UserInfo();
2428 ui.id = 10;
2429 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002430 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002431 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2432
2433 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002434
2435 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2436 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2437 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002438 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002439 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2440 c.flattenToString(), user.getIdentifier(), false, true);
2441 verify(mListeners, never()).setPackageOrComponentEnabled(
2442 any(), anyInt(), anyBoolean(), anyBoolean());
2443 }
2444
2445 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002446 public void testGetAssistantAllowedForUser() throws Exception {
2447 UserHandle user = UserHandle.of(10);
2448 try {
2449 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2450 } catch (IllegalStateException e) {
2451 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2452 throw e;
2453 }
2454 }
2455 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2456 }
2457
2458 @Test
2459 public void testGetAssistantAllowed() throws Exception {
2460 try {
2461 mBinderService.getAllowedNotificationAssistant();
2462 } catch (IllegalStateException e) {
2463 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2464 throw e;
2465 }
2466 }
2467 verify(mAssistants, times(1)).getAllowedComponents(0);
2468 }
2469
2470 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002471 public void testSetDndAccessForUser() throws Exception {
2472 UserHandle user = UserHandle.of(10);
2473 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002474 mBinderService.setNotificationPolicyAccessGrantedForUser(
2475 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002476
2477 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2478 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2479 c.getPackageName(), user.getIdentifier(), true, true);
2480 verify(mAssistants, never()).setPackageOrComponentEnabled(
2481 any(), anyInt(), anyBoolean(), anyBoolean());
2482 verify(mListeners, never()).setPackageOrComponentEnabled(
2483 any(), anyInt(), anyBoolean(), anyBoolean());
2484 }
2485
2486 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002487 public void testSetListenerAccess() throws Exception {
2488 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002489 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002490
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002491 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002492 c.flattenToString(), 0, true, true);
2493 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2494 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002495 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002496 any(), anyInt(), anyBoolean(), anyBoolean());
2497 }
2498
2499 @Test
2500 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002501 List<UserInfo> uis = new ArrayList<>();
2502 UserInfo ui = new UserInfo();
2503 ui.id = 0;
2504 uis.add(ui);
2505 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002506 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002507
2508 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002509
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002510 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002511 c.flattenToString(), 0, true, true);
2512 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2513 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002514 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002515 any(), anyInt(), anyBoolean(), anyBoolean());
2516 }
2517
2518 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002519 public void testSetAssistantAccess_multiProfile() throws Exception {
2520 List<UserInfo> uis = new ArrayList<>();
2521 UserInfo ui = new UserInfo();
2522 ui.id = 0;
2523 uis.add(ui);
2524 UserInfo ui10 = new UserInfo();
2525 ui10.id = 10;
2526 uis.add(ui10);
2527 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2528 ComponentName c = ComponentName.unflattenFromString("package/Component");
2529
2530 mBinderService.setNotificationAssistantAccessGranted(c, true);
2531
2532 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2533 c.flattenToString(), 0, true, true);
2534 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2535 c.flattenToString(), 10, true, true);
2536 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2537 c.flattenToString(), 0, false, true);
2538 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2539 c.flattenToString(), 10, false, true);
2540 verify(mListeners, never()).setPackageOrComponentEnabled(
2541 any(), anyInt(), anyBoolean(), anyBoolean());
2542 }
2543
2544 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002545 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2546 ArrayList<ComponentName> componentList = new ArrayList<>();
2547 ComponentName c = ComponentName.unflattenFromString("package/Component");
2548 componentList.add(c);
2549 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002550 List<UserInfo> uis = new ArrayList<>();
2551 UserInfo ui = new UserInfo();
2552 ui.id = 0;
2553 uis.add(ui);
2554 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002555
Julia Reynolds4afe2642019-05-01 08:42:24 -04002556 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002557
2558 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2559 c.flattenToString(), 0, true, false);
2560 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2561 c.flattenToString(), 0, false, false);
2562 verify(mListeners, never()).setPackageOrComponentEnabled(
2563 any(), anyInt(), anyBoolean(), anyBoolean());
2564 }
2565
2566 @Test
2567 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002568 List<UserInfo> uis = new ArrayList<>();
2569 UserInfo ui = new UserInfo();
2570 ui.id = 10;
2571 uis.add(ui);
2572 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002573 ArrayList<ComponentName> componentList = new ArrayList<>();
2574 ComponentName c = ComponentName.unflattenFromString("package/Component");
2575 componentList.add(c);
2576 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002577 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002578
Julia Reynolds4afe2642019-05-01 08:42:24 -04002579 mBinderService.setNotificationAssistantAccessGrantedForUser(
2580 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002581
2582 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2583 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002584 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002585 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2586 c.flattenToString(), user.getIdentifier(), false, false);
2587 verify(mListeners, never()).setPackageOrComponentEnabled(
2588 any(), anyInt(), anyBoolean(), anyBoolean());
2589 }
2590
2591 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002592 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2593 throws Exception {
2594 List<UserInfo> uis = new ArrayList<>();
2595 UserInfo ui = new UserInfo();
2596 ui.id = 0;
2597 uis.add(ui);
2598 UserInfo ui10 = new UserInfo();
2599 ui10.id = 10;
2600 uis.add(ui10);
2601 UserHandle user = ui.getUserHandle();
2602 ArrayList<ComponentName> componentList = new ArrayList<>();
2603 ComponentName c = ComponentName.unflattenFromString("package/Component");
2604 componentList.add(c);
2605 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2606 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2607
2608 mBinderService.setNotificationAssistantAccessGrantedForUser(
2609 null, user.getIdentifier(), true);
2610
2611 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2612 c.flattenToString(), user.getIdentifier(), true, false);
2613 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2614 c.flattenToString(), ui10.id, true, false);
2615 verify(mAssistants).setUserSet(0, true);
2616 verify(mAssistants).setUserSet(10, true);
2617 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2618 c.flattenToString(), user.getIdentifier(), false, false);
2619 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2620 c.flattenToString(), ui10.id, false, false);
2621 verify(mListeners, never()).setPackageOrComponentEnabled(
2622 any(), anyInt(), anyBoolean(), anyBoolean());
2623 }
2624
2625 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002626 public void testSetDndAccess() throws Exception {
2627 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002628
2629 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002630
2631 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2632 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002633 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002634 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002635 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002636 any(), anyInt(), anyBoolean(), anyBoolean());
2637 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002638
2639 @Test
2640 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2641 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2642 ComponentName c = ComponentName.unflattenFromString("package/Component");
2643 mBinderService.setNotificationListenerAccessGranted(c, true);
2644
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002645 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002646 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002647 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002648 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002649 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002650 any(), anyInt(), anyBoolean(), anyBoolean());
2651 }
2652
2653 @Test
2654 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2655 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2656 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002657 List<UserInfo> uis = new ArrayList<>();
2658 UserInfo ui = new UserInfo();
2659 ui.id = 0;
2660 uis.add(ui);
2661 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2662
Julia Reynolds68263d12017-06-21 14:21:19 -04002663 mBinderService.setNotificationAssistantAccessGranted(c, true);
2664
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002665 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002666 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002667 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002668 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002669 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002670 any(), anyInt(), anyBoolean(), anyBoolean());
2671 }
2672
2673 @Test
2674 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2675 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2676 ComponentName c = ComponentName.unflattenFromString("package/Component");
2677 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2678
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002679 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002680 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002681 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002682 anyString(), anyInt(), anyBoolean(), anyBoolean());
2683 verify(mAssistants, never()).setPackageOrComponentEnabled(
2684 any(), anyInt(), anyBoolean(), anyBoolean());
2685 }
2686
2687 @Test
2688 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2689 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2690 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2691 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002692
2693 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002694
2695 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2696 c.flattenToString(), 0, true, true);
2697 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002698 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002699 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002700 any(), anyInt(), anyBoolean(), anyBoolean());
2701 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002702
2703 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002704 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2705 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2706 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2707 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002708 List<UserInfo> uis = new ArrayList<>();
2709 UserInfo ui = new UserInfo();
2710 ui.id = 0;
2711 uis.add(ui);
2712 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2713
2714 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002715
2716 verify(mListeners, never()).setPackageOrComponentEnabled(
2717 anyString(), anyInt(), anyBoolean(), anyBoolean());
2718 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2719 c.flattenToString(), 0, false, true);
2720 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2721 c.flattenToString(), 0, true, true);
2722 }
2723
2724 @Test
2725 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2726 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2727 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2728 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002729
2730 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002731
2732 verify(mListeners, never()).setPackageOrComponentEnabled(
2733 anyString(), anyInt(), anyBoolean(), anyBoolean());
2734 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2735 c.getPackageName(), 0, true, true);
2736 verify(mAssistants, never()).setPackageOrComponentEnabled(
2737 any(), anyInt(), anyBoolean(), anyBoolean());
2738 }
2739
2740 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002741 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2742 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002743 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002744 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002745 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002746 runnable.run();
2747 waitForIdle();
2748
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002749 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002750 }
2751
2752 @Test
2753 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2754 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002755 NotificationRecord r =
2756 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002757 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002758
2759 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002760 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002761 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002762 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002763 runnable.run();
2764 waitForIdle();
2765
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002766 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002767 }
2768
2769 @Test
2770 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2771 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002772 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2773 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002774 mService.addNotification(r);
2775 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002776
2777 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002778 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002779 runnable.run();
2780 waitForIdle();
2781
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002782 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002783 }
Beverly40239d92017-07-07 10:20:41 -04002784
Julia Reynolds4db59552017-06-30 13:34:01 -04002785 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002786 public void testDontAutogroupIfCritical() throws Exception {
2787 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2788 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2789 mService.addEnqueuedNotification(r);
2790 NotificationManagerService.PostNotificationRunnable runnable =
2791 mService.new PostNotificationRunnable(r.getKey());
2792 runnable.run();
2793
2794 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2795 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2796 runnable = mService.new PostNotificationRunnable(r.getKey());
2797 mService.addEnqueuedNotification(r);
2798
2799 runnable.run();
2800 waitForIdle();
2801
2802 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2803 }
2804
2805 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002806 public void testNoFakeColorizedPermission() throws Exception {
2807 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2808 Notification.Builder nb = new Notification.Builder(mContext,
2809 mTestNotificationChannel.getId())
2810 .setContentTitle("foo")
2811 .setColorized(true)
2812 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2813 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002814 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
2815 "testNoFakeColorizedPermission", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002816 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002817 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2818
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002819 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds4db59552017-06-30 13:34:01 -04002820 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2821 waitForIdle();
2822
Julia Reynolds503ed942017-10-04 16:04:56 -04002823 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002824 PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04002825
2826 assertFalse(posted.getNotification().isColorized());
2827 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002828
2829 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002830 public void testGetNotificationCountLocked() {
2831 String sampleTagToExclude = null;
2832 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002833 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002834 NotificationRecord r =
2835 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002836 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002837
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002838 }
2839 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002840 NotificationRecord r =
2841 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002842 mService.addNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002843 sampleTagToExclude = r.sbn.getTag();
2844 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002845 }
2846
2847 // another package
2848 Notification n =
2849 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2850 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2851 .build();
2852
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002853 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2854 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002855 NotificationRecord otherPackage =
2856 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002857 mService.addEnqueuedNotification(otherPackage);
2858 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002859
2860 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002861 // anything that's currently enqueued or posted
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002862 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002863 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002864 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002865 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002866 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002867
2868 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002869 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002870 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002871
2872 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002873 assertEquals(39, mService.getNotificationCountLocked(
2874 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002875 }
2876
2877 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002878 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002879 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002880 mService.addNotification(r);
2881 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002882
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002883 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04002884 }
2885
2886 @Test
2887 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04002888 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2889 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002890 mService.addNotification(r);
2891 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002892
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002893 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04002894 }
2895
2896 @Test
2897 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04002898 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2899 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002900 mService.addNotification(r);
2901 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002902
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002903 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002904 }
2905
2906 @Test
2907 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002908 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002909 NotificationManagerService.WorkerHandler handler = mock(
2910 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002911 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002912
2913 Map<String, Answer> answers = getSignalExtractorSideEffects();
2914 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002915 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002916 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002917 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002918
2919 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2920
Julia Reynolds503ed942017-10-04 16:04:56 -04002921 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002922 }
2923 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2924 }
2925
2926 @Test
2927 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002928 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002929 NotificationManagerService.WorkerHandler handler = mock(
2930 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002931 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002932
2933 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002934 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002935
Julia Reynolds503ed942017-10-04 16:04:56 -04002936 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002937 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002938 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002939
2940 @Test
2941 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002942 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002943 + "<ranking></ranking>"
2944 + "<enabled_listeners>"
2945 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2946 + "</enabled_listeners>"
2947 + "<enabled_assistants>"
2948 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2949 + "</enabled_assistants>"
2950 + "<dnd_apps>"
2951 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2952 + "</dnd_apps>"
2953 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002954 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002955 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2956 false,
2957 UserHandle.USER_ALL);
2958 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2959 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2960 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002961
2962 // numbers are inflated for setup
2963 verify(mListeners, times(1)).migrateToXml();
2964 verify(mConditionProviders, times(1)).migrateToXml();
2965 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002966 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002967 }
2968
2969 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04002970 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
2971 final String upgradeXml = "<notification-policy version=\"1\">"
2972 + "<snoozed-notifications>></snoozed-notifications>"
2973 + "</notification-policy>";
2974 mService.readPolicyXml(
2975 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2976 false,
2977 UserHandle.USER_ALL);
2978 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class));
2979 }
2980
2981 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002982 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2983 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002984 + "<ranking></ranking>"
2985 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002986 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002987 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2988 false,
2989 UserHandle.USER_ALL);
2990 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2991 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2992 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002993
2994 // numbers are inflated for setup
2995 verify(mListeners, times(2)).migrateToXml();
2996 verify(mConditionProviders, times(2)).migrateToXml();
2997 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002998 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002999 }
3000
Annie Meng8b646fd2019-02-01 18:46:42 +00003001 @Test
3002 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3003 final String policyXml = "<notification-policy version=\"1\">"
3004 + "<ranking></ranking>"
3005 + "<enabled_listeners>"
3006 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3007 + "</enabled_listeners>"
3008 + "<enabled_assistants>"
3009 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3010 + "</enabled_assistants>"
3011 + "<dnd_apps>"
3012 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3013 + "</dnd_apps>"
3014 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003015 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00003016 mService.readPolicyXml(
3017 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3018 true,
3019 10);
3020 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3021 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3022 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3023 }
3024
3025 @Test
3026 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3027 final String policyXml = "<notification-policy version=\"1\">"
3028 + "<ranking></ranking>"
3029 + "<enabled_listeners>"
3030 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3031 + "</enabled_listeners>"
3032 + "<enabled_assistants>"
3033 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3034 + "</enabled_assistants>"
3035 + "<dnd_apps>"
3036 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3037 + "</dnd_apps>"
3038 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003039 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003040 mService.readPolicyXml(
3041 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3042 true,
3043 10);
3044 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3045 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3046 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3047 }
Beverlyd4f96492017-08-02 13:36:11 -04003048
3049 @Test
3050 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3051 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003052 mService.mZenModeHelper = mZenModeHelper;
3053 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003054 new Intent(Intent.ACTION_LOCALE_CHANGED));
3055
3056 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3057 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003058
3059 @Test
3060 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003061 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003062 final ApplicationInfo legacy = new ApplicationInfo();
3063 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3064 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3065 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003066 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3067 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003068 getContext().setMockPackageManager(mPackageManagerClient);
3069
3070 Notification.Builder nb = new Notification.Builder(mContext,
3071 NotificationChannel.DEFAULT_CHANNEL_ID)
3072 .setContentTitle("foo")
3073 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003074 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003075 .setPriority(Notification.PRIORITY_MIN);
3076
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003077 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3078 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003079 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003080
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003081 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3082 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003083 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003084
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003085 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003086 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003087
3088 nb = new Notification.Builder(mContext)
3089 .setContentTitle("foo")
3090 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003091 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003092 .setPriority(Notification.PRIORITY_MIN);
3093
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003094 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3095 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003096 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003097
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003098 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3099 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003100 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3101 waitForIdle();
3102 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003103 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003104
3105 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003106 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003107 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3108 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003109
3110 @Test
3111 public void testStats_updatedOnDirectReply() throws Exception {
3112 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3113 mService.addNotification(r);
3114
3115 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3116 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00003117 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04003118 }
3119
3120 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003121 public void testStats_updatedOnUserExpansion() throws Exception {
3122 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003123 mService.addNotification(r);
3124
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003125 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3126 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00003127 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003128 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003129
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003130 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3131 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00003132 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003133 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3134 }
3135
3136 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003137 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3138 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3139 mService.addNotification(r);
3140
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003141 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3142 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003143 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003144 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
3145
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003146 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3147 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003148 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003149 verify(mAssistants).notifyAssistantExpansionChangedLocked(
3150 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003151 }
3152
3153 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003154 public void testStats_updatedOnViewSettings() throws Exception {
3155 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3156 mService.addNotification(r);
3157
3158 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3159 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3160 }
3161
3162 @Test
3163 public void testStats_updatedOnVisibilityChanged() throws Exception {
3164 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3165 mService.addNotification(r);
3166
Dieter Hsud39f0d52018-04-14 02:08:30 +08003167 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003168 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3169 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
3170 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3171 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3172 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
3173 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3174 }
3175
3176 @Test
3177 public void testStats_dismissalSurface() throws Exception {
3178 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3179 mService.addNotification(r);
3180
Dieter Hsud39f0d52018-04-14 02:08:30 +08003181 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003182 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003183 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3184 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003185 waitForIdle();
3186
3187 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
3188 }
3189
3190 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003191 public void testStats_dismissalSentiment() throws Exception {
3192 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3193 mService.addNotification(r);
3194
3195 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
3196 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
3197 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3198 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3199 waitForIdle();
3200
3201 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3202 r.getStats().getDismissalSentiment());
3203 }
3204
3205 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003206 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003207 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3208 mService.addNotification(r);
3209 NotificationManagerService.WorkerHandler handler = mock(
3210 NotificationManagerService.WorkerHandler.class);
3211 mService.setHandler(handler);
3212
Julia Reynolds70aaea72018-07-13 13:38:34 -04003213 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3214
Julia Reynolds503ed942017-10-04 16:04:56 -04003215 Bundle signals = new Bundle();
3216 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003217 USER_SENTIMENT_NEGATIVE);
3218 Adjustment adjustment = new Adjustment(
3219 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3220 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3221
3222 waitForIdle();
3223
3224 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3225 }
3226
3227 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003228 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003229 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3230 mService.addNotification(r);
3231 NotificationManagerService.WorkerHandler handler = mock(
3232 NotificationManagerService.WorkerHandler.class);
3233 mService.setHandler(handler);
3234
3235 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003236 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003237 Adjustment adjustment = new Adjustment(
3238 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3239 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3240 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3241
3242 waitForIdle();
3243
3244 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3245 verify(handler, times(1)).scheduleCancelNotification(any());
3246 }
3247
3248 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003249 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3250 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3251 mService.addEnqueuedNotification(r);
3252 NotificationManagerService.WorkerHandler handler = mock(
3253 NotificationManagerService.WorkerHandler.class);
3254 mService.setHandler(handler);
3255 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3256
3257 Bundle signals = new Bundle();
3258 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3259 USER_SENTIMENT_NEGATIVE);
3260 Adjustment adjustment = new Adjustment(
3261 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3262 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3263
3264 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3265 }
3266
3267 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003268 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003269 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3270 mService.addEnqueuedNotification(r);
3271 NotificationManagerService.WorkerHandler handler = mock(
3272 NotificationManagerService.WorkerHandler.class);
3273 mService.setHandler(handler);
3274 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3275
3276 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003277 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003278 Adjustment adjustment = new Adjustment(
3279 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3280 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3281
3282 assertEquals(IMPORTANCE_LOW, r.getImportance());
3283 }
3284
3285 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003286 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3287 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3288 mService.addEnqueuedNotification(r);
3289 NotificationManagerService.WorkerHandler handler = mock(
3290 NotificationManagerService.WorkerHandler.class);
3291 mService.setHandler(handler);
3292 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3293
3294 Bundle signals = new Bundle();
3295 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3296 USER_SENTIMENT_NEGATIVE);
3297 Adjustment adjustment = new Adjustment(
3298 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3299 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3300
3301 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3302
3303 waitForIdle();
3304
3305 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3306 }
3307
3308 @Test
3309 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3310 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3311 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003312 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3313
3314 Bundle signals = new Bundle();
3315 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3316 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003317 Adjustment adjustment = new Adjustment(
3318 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3319 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3320
3321 waitForIdle();
3322
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003323 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003324 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003325
3326 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003327 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3328 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3329 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003330 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003331
3332 Bundle signals = new Bundle();
3333 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003334 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003335 Adjustment adjustment = new Adjustment(
3336 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3337 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3338
3339 waitForIdle();
3340
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003341 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003342 }
3343
3344 @Test
3345 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3346 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3347 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003348 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003349
3350 Bundle signals = new Bundle();
3351 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003352 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003353 Adjustment adjustment = new Adjustment(
3354 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3355 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3356
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003357 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003358 }
3359
3360 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003361 public void testRestore() throws Exception {
3362 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003363 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003364 assertEquals(1, mService.countSystemChecks - systemChecks);
3365 }
3366
3367 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003368 public void testBackupEmptySound() throws Exception {
3369 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3370 channel.setSound(Uri.EMPTY, null);
3371
3372 XmlSerializer serializer = new FastXmlSerializer();
3373 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3374 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3375 channel.writeXmlForBackup(serializer, getContext());
3376
3377 XmlPullParser parser = Xml.newPullParser();
3378 parser.setInput(new BufferedInputStream(
3379 new ByteArrayInputStream(baos.toByteArray())), null);
3380 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3381 restored.populateFromXmlForRestore(parser, getContext());
3382
3383 assertNull(restored.getSound());
3384 }
3385
3386 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003387 public void testBackup() throws Exception {
3388 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04003389 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3390 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003391 mBinderService.getBackupPayload(1);
3392 assertEquals(1, mService.countSystemChecks - systemChecks);
3393 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003394
3395 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003396 public void testEmptyVibration_noException() throws Exception {
3397 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3398 channel.setVibrationPattern(new long[0]);
3399
3400 XmlSerializer serializer = new FastXmlSerializer();
3401 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3402 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3403 channel.writeXml(serializer);
3404 }
3405
3406 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003407 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003408 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003409 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003410 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3411 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003412 message1.setData("",
3413 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003414 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003415 message2.setData("",
3416 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003417
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003418 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003419 .setContentTitle("foo")
3420 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3421 .setStyle(new Notification.MessagingStyle("")
3422 .addMessage(message1)
3423 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003424 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3425 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003426
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003427 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003428 reset(mUgm);
3429 reset(mUgmInternal);
3430 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003431 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003432 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003433 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003434 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003435 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003436 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3437
3438 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003439 .setContentTitle("foo")
3440 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3441 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003442 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3443 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003444
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003445 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003446 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003447 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003448 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003449 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3450 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003451
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003452 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003453 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003454 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003455 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003456 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003457 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003458
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003459 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003460 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003461 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003462 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003463 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003464 anyInt(), anyInt());
3465 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003466
3467 @Test
Robin Leed107af62018-04-27 13:55:56 +02003468 public void testVisitUris() throws Exception {
3469 final Uri audioContents = Uri.parse("content://com.example/audio");
3470 final Uri backgroundImage = Uri.parse("content://com.example/background");
3471
3472 Bundle extras = new Bundle();
3473 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3474 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3475
3476 Notification n = new Notification.Builder(mContext, "a")
3477 .setContentTitle("notification with uris")
3478 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3479 .addExtras(extras)
3480 .build();
3481
3482 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3483 n.visitUris(visitor);
3484 verify(visitor, times(1)).accept(eq(audioContents));
3485 verify(visitor, times(1)).accept(eq(backgroundImage));
3486 }
3487
3488 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003489 public void testSetNotificationPolicy_preP_setOldFields() {
3490 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3491 mService.mZenModeHelper = mZenModeHelper;
3492 NotificationManager.Policy userPolicy =
3493 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3494 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3495
3496 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3497 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3498
3499 int expected = SUPPRESSED_EFFECT_BADGE
3500 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003501 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3502 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003503 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3504
3505 assertEquals(expected, actual);
3506 }
3507
3508 @Test
3509 public void testSetNotificationPolicy_preP_setNewFields() {
3510 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3511 mService.mZenModeHelper = mZenModeHelper;
3512 NotificationManager.Policy userPolicy =
3513 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3514 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3515
3516 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3517 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3518
3519 int expected = SUPPRESSED_EFFECT_BADGE;
3520 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3521
3522 assertEquals(expected, actual);
3523 }
3524
3525 @Test
3526 public void testSetNotificationPolicy_preP_setOldNewFields() {
3527 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3528 mService.mZenModeHelper = mZenModeHelper;
3529 NotificationManager.Policy userPolicy =
3530 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3531 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3532
3533 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3534 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3535
3536 int expected =
3537 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3538 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3539
3540 assertEquals(expected, actual);
3541 }
3542
3543 @Test
3544 public void testSetNotificationPolicy_P_setOldFields() {
3545 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3546 mService.mZenModeHelper = mZenModeHelper;
3547 NotificationManager.Policy userPolicy =
3548 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3549 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3550
3551 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3552 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3553
3554 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3555 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3556 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3557 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3558
3559 assertEquals(expected, actual);
3560 }
3561
3562 @Test
3563 public void testSetNotificationPolicy_P_setNewFields() {
3564 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3565 mService.mZenModeHelper = mZenModeHelper;
3566 NotificationManager.Policy userPolicy =
3567 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3568 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3569
3570 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3571 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3572 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3573
3574 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3575 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3576 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3577 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3578
3579 assertEquals(expected, actual);
3580 }
3581
3582 @Test
3583 public void testSetNotificationPolicy_P_setOldNewFields() {
3584 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3585 mService.mZenModeHelper = mZenModeHelper;
3586 NotificationManager.Policy userPolicy =
3587 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3588 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3589
3590 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3591 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3592
3593 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3594 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3595
3596 assertEquals(expected, actual);
3597
3598 appPolicy = new NotificationManager.Policy(0, 0, 0,
3599 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3600 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3601
3602 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3603 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3604 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3605
3606 assertEquals(expected, actual);
3607 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003608
3609 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003610 public void testVisualDifference_foreground() {
3611 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3612 .setContentTitle("foo");
3613 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3614 nb1.build(), new UserHandle(mUid), null, 0);
3615 NotificationRecord r1 =
3616 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3617
3618 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3619 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3620 .setContentTitle("bar");
3621 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3622 nb2.build(), new UserHandle(mUid), null, 0);
3623 NotificationRecord r2 =
3624 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3625
3626 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3627 }
3628
3629 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003630 public void testVisualDifference_diffTitle() {
3631 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3632 .setContentTitle("foo");
3633 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3634 nb1.build(), new UserHandle(mUid), null, 0);
3635 NotificationRecord r1 =
3636 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3637
3638 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3639 .setContentTitle("bar");
3640 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3641 nb2.build(), new UserHandle(mUid), null, 0);
3642 NotificationRecord r2 =
3643 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3644
3645 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3646 }
3647
3648 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003649 public void testVisualDifference_inboxStyle() {
3650 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3651 .setStyle(new Notification.InboxStyle()
3652 .addLine("line1").addLine("line2"));
3653 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3654 nb1.build(), new UserHandle(mUid), null, 0);
3655 NotificationRecord r1 =
3656 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3657
3658 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3659 .setStyle(new Notification.InboxStyle()
3660 .addLine("line1").addLine("line2_changed"));
3661 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3662 nb2.build(), new UserHandle(mUid), null, 0);
3663 NotificationRecord r2 =
3664 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3665
3666 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3667
3668 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3669 .setStyle(new Notification.InboxStyle()
3670 .addLine("line1"));
3671 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3672 nb3.build(), new UserHandle(mUid), null, 0);
3673 NotificationRecord r3 =
3674 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3675
3676 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3677
3678 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3679 .setStyle(new Notification.InboxStyle()
3680 .addLine("line1").addLine("line2").addLine("line3"));
3681 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3682 nb4.build(), new UserHandle(mUid), null, 0);
3683 NotificationRecord r4 =
3684 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3685
3686 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3687
3688 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3689 .setContentText("not an inbox");
3690 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3691 nb5.build(), new UserHandle(mUid), null, 0);
3692 NotificationRecord r5 =
3693 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3694
3695 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3696 }
3697
3698 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003699 public void testVisualDifference_diffText() {
3700 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3701 .setContentText("foo");
3702 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3703 nb1.build(), new UserHandle(mUid), null, 0);
3704 NotificationRecord r1 =
3705 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3706
3707 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3708 .setContentText("bar");
3709 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3710 nb2.build(), new UserHandle(mUid), null, 0);
3711 NotificationRecord r2 =
3712 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3713
3714 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3715 }
3716
3717 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003718 public void testVisualDifference_sameText() {
3719 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3720 .setContentText("foo");
3721 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3722 nb1.build(), new UserHandle(mUid), null, 0);
3723 NotificationRecord r1 =
3724 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3725
3726 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3727 .setContentText("foo");
3728 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3729 nb2.build(), new UserHandle(mUid), null, 0);
3730 NotificationRecord r2 =
3731 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3732
3733 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3734 }
3735
3736 @Test
3737 public void testVisualDifference_sameTextButStyled() {
3738 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3739 .setContentText(Html.fromHtml("<b>foo</b>"));
3740 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3741 nb1.build(), new UserHandle(mUid), null, 0);
3742 NotificationRecord r1 =
3743 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3744
3745 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3746 .setContentText(Html.fromHtml("<b>foo</b>"));
3747 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3748 nb2.build(), new UserHandle(mUid), null, 0);
3749 NotificationRecord r2 =
3750 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3751
3752 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3753 }
3754
3755 @Test
3756 public void testVisualDifference_diffTextButStyled() {
3757 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3758 .setContentText(Html.fromHtml("<b>foo</b>"));
3759 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3760 nb1.build(), new UserHandle(mUid), null, 0);
3761 NotificationRecord r1 =
3762 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3763
3764 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3765 .setContentText(Html.fromHtml("<b>bar</b>"));
3766 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3767 nb2.build(), new UserHandle(mUid), null, 0);
3768 NotificationRecord r2 =
3769 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3770
3771 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3772 }
3773
3774 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003775 public void testVisualDifference_diffProgress() {
3776 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3777 .setProgress(100, 90, false);
3778 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3779 nb1.build(), new UserHandle(mUid), null, 0);
3780 NotificationRecord r1 =
3781 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3782
3783 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3784 .setProgress(100, 100, false);
3785 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3786 nb2.build(), new UserHandle(mUid), null, 0);
3787 NotificationRecord r2 =
3788 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3789
3790 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3791 }
3792
3793 @Test
3794 public void testVisualDifference_diffProgressNotDone() {
3795 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3796 .setProgress(100, 90, false);
3797 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3798 nb1.build(), new UserHandle(mUid), null, 0);
3799 NotificationRecord r1 =
3800 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3801
3802 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3803 .setProgress(100, 91, false);
3804 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3805 nb2.build(), new UserHandle(mUid), null, 0);
3806 NotificationRecord r2 =
3807 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3808
3809 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3810 }
Beverly5a20a5e2018-03-06 15:02:44 -05003811
3812 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003813 public void testVisualDifference_sameProgressStillDone() {
3814 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3815 .setProgress(100, 100, false);
3816 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3817 nb1.build(), new UserHandle(mUid), null, 0);
3818 NotificationRecord r1 =
3819 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3820
3821 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3822 .setProgress(100, 100, false);
3823 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3824 nb2.build(), new UserHandle(mUid), null, 0);
3825 NotificationRecord r2 =
3826 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3827
3828 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3829 }
3830
3831 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003832 public void testVisualDifference_summary() {
3833 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3834 .setGroup("bananas")
3835 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3836 .setContentText("foo");
3837 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3838 nb1.build(), new UserHandle(mUid), null, 0);
3839 NotificationRecord r1 =
3840 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3841
3842 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3843 .setGroup("bananas")
3844 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3845 .setContentText("bar");
3846 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3847 nb2.build(), new UserHandle(mUid), null, 0);
3848 NotificationRecord r2 =
3849 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3850
3851 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3852 }
3853
3854 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003855 public void testVisualDifference_summaryNewNotification() {
3856 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3857 .setGroup("bananas")
3858 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3859 .setContentText("bar");
3860 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3861 nb2.build(), new UserHandle(mUid), null, 0);
3862 NotificationRecord r2 =
3863 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3864
3865 assertFalse(mService.isVisuallyInterruptive(null, r2));
3866 }
3867
3868 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003869 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3870 // post 2 notification from this package
3871 final NotificationRecord notif1 = generateNotificationRecord(
3872 mTestNotificationChannel, 1, null, true);
3873 final NotificationRecord notif2 = generateNotificationRecord(
3874 mTestNotificationChannel, 2, null, false);
3875 mService.addNotification(notif1);
3876 mService.addNotification(notif2);
3877
3878 // on broadcast, hide the 2 notifications
3879 mService.simulatePackageSuspendBroadcast(true, PKG);
3880 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3881 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3882 assertEquals(2, captorHide.getValue().size());
3883
3884 // on broadcast, unhide the 2 notifications
3885 mService.simulatePackageSuspendBroadcast(false, PKG);
3886 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3887 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3888 assertEquals(2, captorUnhide.getValue().size());
3889 }
3890
3891 @Test
3892 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3893 // post 2 notification from this package
3894 final NotificationRecord notif1 = generateNotificationRecord(
3895 mTestNotificationChannel, 1, null, true);
3896 final NotificationRecord notif2 = generateNotificationRecord(
3897 mTestNotificationChannel, 2, null, false);
3898 mService.addNotification(notif1);
3899 mService.addNotification(notif2);
3900
3901 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3902 mService.simulatePackageSuspendBroadcast(true, "test_package");
3903 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3904 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3905 assertEquals(0, captor.getValue().size());
3906 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003907
3908 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003909 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3910 // Post 2 notifications from 2 packages
3911 NotificationRecord pkgA = new NotificationRecord(mContext,
3912 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3913 mService.addNotification(pkgA);
3914 NotificationRecord pkgB = new NotificationRecord(mContext,
3915 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3916 mService.addNotification(pkgB);
3917
3918 // on broadcast, hide one of the packages
3919 mService.simulatePackageDistractionBroadcast(
3920 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3921 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3922 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3923 assertEquals(1, captorHide.getValue().size());
3924 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3925
3926 // on broadcast, unhide the package
3927 mService.simulatePackageDistractionBroadcast(
3928 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3929 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3930 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3931 assertEquals(1, captorUnhide.getValue().size());
3932 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3933 }
3934
3935 @Test
3936 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3937 // Post 2 notifications from 2 packages
3938 NotificationRecord pkgA = new NotificationRecord(mContext,
3939 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3940 mService.addNotification(pkgA);
3941 NotificationRecord pkgB = new NotificationRecord(mContext,
3942 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3943 mService.addNotification(pkgB);
3944
3945 // on broadcast, hide one of the packages
3946 mService.simulatePackageDistractionBroadcast(
3947 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3948 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003949
3950 // should be called only once.
3951 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003952 assertEquals(2, captorHide.getValue().size());
3953 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3954 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3955
3956 // on broadcast, unhide the package
3957 mService.simulatePackageDistractionBroadcast(
3958 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3959 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003960
3961 // should be called only once.
3962 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003963 assertEquals(2, captorUnhide.getValue().size());
3964 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3965 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3966 }
3967
3968 @Test
3969 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3970 // post notification from this package
3971 final NotificationRecord notif1 = generateNotificationRecord(
3972 mTestNotificationChannel, 1, null, true);
3973 mService.addNotification(notif1);
3974
3975 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3976 mService.simulatePackageDistractionBroadcast(
3977 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3978 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3979 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3980 assertEquals(0, captor.getValue().size());
3981 }
3982
3983 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003984 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3985 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3986 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3987 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3988 .thenReturn(new String[] {"a", "b", "c"});
3989 when(mContext.getResources()).thenReturn(mResources);
3990
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003991 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003992 }
3993
3994 @Test
3995 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3996 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3997 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3998 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3999 .thenReturn(new String[] {"a", "b", "c"});
4000 when(mContext.getResources()).thenReturn(mResources);
4001
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004002 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004003 }
4004
4005 @Test
4006 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
4007 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
4008 when(mActivityManager.isLowRamDevice()).thenReturn(true);
4009 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4010 .thenReturn(new String[] {"a", "b", "c"});
4011 when(mContext.getResources()).thenReturn(mResources);
4012
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004013 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004014 }
4015
4016 @Test
4017 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
4018 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4019 when(mActivityManager.isLowRamDevice()).thenReturn(true);
4020 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4021 .thenReturn(new String[] {"a", "b", "c"});
4022 when(mContext.getResources()).thenReturn(mResources);
4023
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004024 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004025 }
4026
4027 @Test
4028 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
4029 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
4030 when(mActivityManager.isLowRamDevice()).thenReturn(false);
4031 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4032 .thenReturn(new String[] {"a", "b", "c"});
4033 when(mContext.getResources()).thenReturn(mResources);
4034
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004035 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004036 }
4037
4038 @Test
4039 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
4040 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4041 when(mActivityManager.isLowRamDevice()).thenReturn(false);
4042 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4043 .thenReturn(new String[] {"a", "b", "c"});
4044 when(mContext.getResources()).thenReturn(mResources);
4045
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004046 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4047 }
4048
4049 @Test
4050 public void testCanUseManagedServices_hasPermission() throws Exception {
4051 when(mPackageManager.checkPermission("perm", "pkg", 0))
4052 .thenReturn(PackageManager.PERMISSION_GRANTED);
4053
4054 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4055 }
4056
4057 @Test
4058 public void testCanUseManagedServices_noPermission() throws Exception {
4059 when(mPackageManager.checkPermission("perm", "pkg", 0))
4060 .thenReturn(PackageManager.PERMISSION_DENIED);
4061
4062 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4063 }
4064
4065 @Test
4066 public void testCanUseManagedServices_permDoesNotMatter() {
4067 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004068 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004069
4070 @Test
4071 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4072 final NotificationRecord r = generateNotificationRecord(
4073 mTestNotificationChannel, 1, null, true);
4074 r.setTextChanged(true);
4075 mService.addNotification(r);
4076
4077 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4078 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4079 new NotificationVisibility[]{});
4080
4081 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4082 }
4083
4084 @Test
4085 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4086 throws RemoteException {
4087 final NotificationRecord r = generateNotificationRecord(
4088 mTestNotificationChannel, 1, null, true);
4089 r.setTextChanged(true);
4090 mService.addNotification(r);
4091
4092 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4093
4094 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4095 }
4096
4097 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004098 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004099 throws RemoteException {
4100 final NotificationRecord r = generateNotificationRecord(
4101 mTestNotificationChannel, 1, null, true);
4102 r.setInterruptive(true);
4103 mService.addNotification(r);
4104
4105 mService.maybeRecordInterruptionLocked(r);
4106 mService.maybeRecordInterruptionLocked(r);
4107
4108 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4109 anyString(), anyString(), anyInt());
4110 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004111
4112 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004113 public void testBubble() throws Exception {
4114 mBinderService.setBubblesAllowed(PKG, mUid, false);
4115 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004116 }
4117
4118 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08004119 public void testUserApprovedBubblesForPackage() throws Exception {
4120 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4121 mBinderService.setBubblesAllowed(PKG, mUid, true);
4122 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4123 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
4124 }
4125
4126 @Test
4127 public void testUserRejectsBubblesForPackage() throws Exception {
4128 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4129 mBinderService.setBubblesAllowed(PKG, mUid, false);
4130 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4131 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
4132 }
4133
4134 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004135 public void testIsCallerInstantApp_primaryUser() throws Exception {
4136 ApplicationInfo info = new ApplicationInfo();
4137 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4138 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004139 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004140
Julia Reynolds268647a2018-10-25 16:54:27 -04004141 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004142
4143 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004144 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004145 }
4146
4147 @Test
4148 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4149 ApplicationInfo info = new ApplicationInfo();
4150 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4151 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4152 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004153 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004154
Julia Reynolds268647a2018-10-25 16:54:27 -04004155 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004156 }
4157
4158 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004159 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4160 ApplicationInfo info = new ApplicationInfo();
4161 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004162 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004163 .thenReturn(info);
4164 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4165
4166 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4167
4168 info.privateFlags = 0;
4169 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4170 }
4171
4172 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004173 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4174 ApplicationInfo info = new ApplicationInfo();
4175 info.uid = Binder.getCallingUid();
4176 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4177 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4178
4179 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4180
4181 assertEquals(info.uid, actualUid);
4182 }
4183
4184 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004185 public void testResolveNotificationUid_sameApp() throws Exception {
4186 ApplicationInfo info = new ApplicationInfo();
4187 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004188 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004189
4190 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4191
4192 assertEquals(info.uid, actualUid);
4193 }
4194
4195 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004196 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004197 ApplicationInfo info = new ApplicationInfo();
4198 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004199 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004200
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004201 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4202
4203 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004204 }
4205
4206 @Test
4207 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4208 ApplicationInfo info = new ApplicationInfo();
4209 info.uid = 1356347;
4210 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4211
4212 try {
4213 mService.resolveNotificationUid("caller", "caller", 9, 0);
4214 fail("Incorrect uid didn't throw security exception");
4215 } catch (SecurityException e) {
4216 // yay
4217 }
4218 }
4219
4220 @Test
4221 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4222 int expectedUid = 123;
4223
4224 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4225 mService.setPreferencesHelper(mPreferencesHelper);
4226 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4227 .thenReturn(true);
4228
4229 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4230 }
4231
4232 @Test
4233 public void testResolveNotificationUid_androidAllowed() throws Exception {
4234 int expectedUid = 123;
4235
4236 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4237 // no delegate
4238
4239 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4240 }
4241
4242 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004243 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4244 final String notReal = "NOT REAL";
4245 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4246 PackageManager.NameNotFoundException.class);
4247 ApplicationInfo ai = new ApplicationInfo();
4248 ai.uid = -1;
4249 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4250
4251 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4252 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004253 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4254 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004255 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4256 fail("can't post notifications for nonexistent packages, even if you exist");
4257 } catch (SecurityException e) {
4258 // yay
4259 }
4260 }
4261
4262 @Test
4263 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4264 final String notReal = "NOT REAL";
4265 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4266 PackageManager.NameNotFoundException.class);
4267 ApplicationInfo ai = new ApplicationInfo();
4268 ai.uid = -1;
4269 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4270
4271 // unlike the post case, ignore instead of throwing
4272 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4273
4274 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4275 sbn.getId(), sbn.getUserId());
4276 }
4277
4278 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004279 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4280 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4281 // no delegate
4282
4283 try {
4284 mService.resolveNotificationUid("caller", "target", 9, 0);
4285 fail("Incorrect uid didn't throw security exception");
4286 } catch (SecurityException e) {
4287 // yay
4288 }
4289 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004290
4291 @Test
4292 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4293 Notification n = new Notification.Builder(mContext, "").build();
4294 n.flags |= FLAG_FOREGROUND_SERVICE;
4295
4296 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4297 n, new UserHandle(mUid), null, 0);
4298 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4299
4300 mService.addEnqueuedNotification(r);
4301
4302 mInternalService.removeForegroundServiceFlagFromNotification(
4303 PKG, r.sbn.getId(), r.sbn.getUserId());
4304
4305 waitForIdle();
4306
4307 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4308 }
4309
4310 @Test
4311 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4312 Notification n = new Notification.Builder(mContext, "").build();
4313 n.flags |= FLAG_FOREGROUND_SERVICE;
4314
4315 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4316 n, new UserHandle(mUid), null, 0);
4317 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4318
4319 mService.addNotification(r);
4320
4321 mInternalService.removeForegroundServiceFlagFromNotification(
4322 PKG, r.sbn.getId(), r.sbn.getUserId());
4323
4324 waitForIdle();
4325
4326 ArgumentCaptor<NotificationRecord> captor =
4327 ArgumentCaptor.forClass(NotificationRecord.class);
4328 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4329
4330 assertEquals(0, captor.getValue().getNotification().flags);
4331 }
Beverly58b24532018-10-02 09:08:23 -04004332
4333 @Test
4334 public void testAllowForegroundToasts() throws Exception {
4335 final String testPackage = "testPackageName";
4336 assertEquals(0, mService.mToastQueue.size());
4337 mService.isSystemUid = false;
4338
4339 // package is not suspended
4340 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4341 .thenReturn(false);
4342
4343 // notifications from this package are blocked by the user
4344 mService.setPreferencesHelper(mPreferencesHelper);
4345 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4346
4347 // this app is in the foreground
4348 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4349
4350 // enqueue toast -> toast should still enqueue
4351 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4352 new TestableToastCallback(), 2000, 0);
4353 assertEquals(1, mService.mToastQueue.size());
4354 }
4355
4356 @Test
4357 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4358 final String testPackage = "testPackageName";
4359 assertEquals(0, mService.mToastQueue.size());
4360 mService.isSystemUid = false;
4361
4362 // package is suspended
4363 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4364 .thenReturn(true);
4365
4366 // notifications from this package are NOT blocked by the user
4367 mService.setPreferencesHelper(mPreferencesHelper);
4368 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4369
4370 // enqueue toast -> no toasts enqueued
4371 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4372 new TestableToastCallback(), 2000, 0);
4373 assertEquals(0, mService.mToastQueue.size());
4374 }
4375
4376 @Test
4377 public void testDisallowToastsFromBlockedApps() throws Exception {
4378 final String testPackage = "testPackageName";
4379 assertEquals(0, mService.mToastQueue.size());
4380 mService.isSystemUid = false;
4381
4382 // package is not suspended
4383 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4384 .thenReturn(false);
4385
4386 // notifications from this package are blocked by the user
4387 mService.setPreferencesHelper(mPreferencesHelper);
4388 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4389
4390 // this app is NOT in the foreground
4391 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4392
4393 // enqueue toast -> no toasts enqueued
4394 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4395 new TestableToastCallback(), 2000, 0);
4396 assertEquals(0, mService.mToastQueue.size());
4397 }
4398
4399 @Test
4400 public void testAlwaysAllowSystemToasts() throws Exception {
4401 final String testPackage = "testPackageName";
4402 assertEquals(0, mService.mToastQueue.size());
4403 mService.isSystemUid = true;
4404
4405 // package is suspended
4406 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4407 .thenReturn(true);
4408
4409 // notifications from this package ARE blocked by the user
4410 mService.setPreferencesHelper(mPreferencesHelper);
4411 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4412
4413 // this app is NOT in the foreground
4414 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4415
4416 // enqueue toast -> system toast can still be enqueued
4417 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4418 new TestableToastCallback(), 2000, 0);
4419 assertEquals(1, mService.mToastQueue.size());
4420 }
Tony Mak29996702018-11-26 16:23:34 +00004421
4422 @Test
4423 public void testOnNotificationSmartReplySent() {
4424 final int replyIndex = 2;
4425 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004426 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004427 final boolean generatedByAssistant = true;
4428
4429 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004430 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004431 mService.addNotification(r);
4432
4433 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004434 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4435 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004436 verify(mAssistants).notifyAssistantSuggestedReplySent(
4437 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4438 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004439
4440 @Test
4441 public void testOnNotificationActionClick() {
4442 final int actionIndex = 2;
4443 final Notification.Action action =
4444 new Notification.Action.Builder(null, "text", null).build();
4445 final boolean generatedByAssistant = false;
4446
4447 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4448 mService.addNotification(r);
4449
4450 NotificationVisibility notificationVisibility =
4451 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4452 mService.mNotificationDelegate.onNotificationActionClick(
4453 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4454 generatedByAssistant);
4455 verify(mAssistants).notifyAssistantActionClicked(
4456 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4457 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004458
4459 @Test
4460 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4461 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4462 mService.addNotification(r);
4463
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004464 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4465 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004466 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4467 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4468 };
4469 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4470 new NotificationVisibility[0]);
4471
4472 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4473 }
4474
4475 @Test
4476 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4477 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4478 mService.addNotification(r);
4479
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004480 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4481 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004482
4483 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4484 }
4485
4486 @Test
4487 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4488 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4489 mService.addNotification(r);
4490
Julia Reynolds95334132018-12-19 11:15:35 -05004491 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004492 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4493 };
4494 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4495 new NotificationVisibility[0]);
4496
4497 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4498 }
Julia Reynolds95334132018-12-19 11:15:35 -05004499
4500 public void testReportSeen_delegated() {
4501 Notification.Builder nb =
4502 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4503 .setContentTitle("foo")
4504 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4505
4506 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4507 nb.build(), new UserHandle(mUid), null, 0);
4508 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4509
4510 mService.reportSeen(r);
4511 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4512
4513 }
4514
4515 @Test
4516 public void testReportSeen_notDelegated() {
4517 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4518
4519 mService.reportSeen(r);
4520 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4521 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004522
4523 @Test
4524 public void testNotificationStats_notificationError() {
4525 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4526 mService.addNotification(r);
4527
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004528 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.sbn.getId(),
4529 r.sbn.getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004530 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4531 new UserHandle(mUid), null, 0);
4532 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4533 mService.addEnqueuedNotification(update);
4534 assertNull(update.sbn.getNotification().getSmallIcon());
4535
4536 NotificationManagerService.PostNotificationRunnable runnable =
4537 mService.new PostNotificationRunnable(update.getKey());
4538 runnable.run();
4539 waitForIdle();
4540
4541 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4542 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4543 assertNotNull(captor.getValue());
4544 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004545
4546 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004547 public void testCanNotifyAsUser_crossUser() throws Exception {
4548 // same user no problem
4549 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4550
4551 // cross user, no permission, problem
4552 try {
4553 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4554 fail("Should not be callable cross user without cross user permission");
4555 } catch (SecurityException e) {
4556 // good
4557 }
4558
4559 // cross user, with permission, no problem
4560 TestablePermissions perms = mContext.getTestablePermissions();
4561 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4562 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4563 }
4564
4565 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004566 public void testgetNotificationChannels_crossUser() throws Exception {
4567 // same user no problem
4568 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4569
4570 // cross user, no permission, problem
4571 try {
4572 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4573 fail("Should not be callable cross user without cross user permission");
4574 } catch (SecurityException e) {
4575 // good
4576 }
4577
4578 // cross user, with permission, no problem
4579 TestablePermissions perms = mContext.getTestablePermissions();
4580 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4581 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4582 }
4583
4584 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004585 public void setDefaultAssistantForUser_fromConfigXml() {
4586 clearDeviceConfig();
4587 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04004588 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004589 when(mResources
4590 .getString(
4591 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4592 .thenReturn(xmlConfig.flattenToString());
4593 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04004594 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
4595 .thenReturn(components);
4596 when(mAssistants.getDefaultComponents())
4597 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00004598 mService.setNotificationAssistantAccessGrantedCallback(
4599 mNotificationAssistantAccessGrantedCallback);
4600
Jay Aliomer4204f252019-08-26 11:36:53 -04004601
Tony Mak9a3c1f12019-03-04 16:04:42 +00004602 mService.setDefaultAssistantForUser(0);
4603
4604 verify(mNotificationAssistantAccessGrantedCallback)
4605 .onGranted(eq(xmlConfig), eq(0), eq(true));
4606 }
4607
4608 @Test
4609 public void setDefaultAssistantForUser_fromDeviceConfig() {
4610 ComponentName xmlConfig = new ComponentName("xml", "config");
4611 ComponentName deviceConfig = new ComponentName("device", "config");
4612 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4613 when(mResources
4614 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4615 .thenReturn(xmlConfig.flattenToString());
4616 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04004617 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00004618 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04004619 when(mAssistants.getDefaultComponents())
4620 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004621 mService.setNotificationAssistantAccessGrantedCallback(
4622 mNotificationAssistantAccessGrantedCallback);
4623
4624 mService.setDefaultAssistantForUser(0);
4625
4626 verify(mNotificationAssistantAccessGrantedCallback)
4627 .onGranted(eq(deviceConfig), eq(0), eq(true));
4628 }
4629
4630 @Test
4631 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4632 ComponentName xmlConfig = new ComponentName("xml", "config");
4633 ComponentName deviceConfig = new ComponentName("device", "config");
4634 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4635 when(mResources
4636 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4637 .thenReturn(xmlConfig.flattenToString());
4638 when(mContext.getResources()).thenReturn(mResources);
4639 // Only xmlConfig is valid, deviceConfig is not.
4640 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04004641 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
4642 when(mAssistants.getDefaultComponents())
4643 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004644 mService.setNotificationAssistantAccessGrantedCallback(
4645 mNotificationAssistantAccessGrantedCallback);
4646
4647 mService.setDefaultAssistantForUser(0);
4648
4649 verify(mNotificationAssistantAccessGrantedCallback)
4650 .onGranted(eq(xmlConfig), eq(0), eq(true));
4651 }
4652
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004653 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04004654 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
4655 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
4656 generateResetComponentValues();
4657 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
4658 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
4659 ComponentName deviceConfig1 = new ComponentName("device", "config1");
4660 ComponentName deviceConfig2 = new ComponentName("device", "config2");
4661 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
4662 changes.put(false, new ArrayList());
4663 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
4664 mService.getBinderService().clearData("device", 0, false);
4665 verify(mAssistants, times(1))
4666 .setPackageOrComponentEnabled(
4667 eq("device/config2"),
4668 eq(0), eq(true), eq(false));
4669 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4670 eq("device"), eq(0), eq(false), eq(true));
4671 }
4672
4673 @Test
4674 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
4675 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
4676 generateResetComponentValues();
4677 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
4678 ComponentName deviceConfig = new ComponentName("device", "config");
4679 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
4680 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
4681 changes.put(false, new ArrayList());
4682 when(mListeners.resetComponents(anyString(), anyInt()))
4683 .thenReturn(changes);
4684 mService.getBinderService().clearData("device", 0, false);
4685 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4686 eq("device"), eq(0), eq(false), eq(true));
4687 }
4688
4689 @Test
4690 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
4691 ComponentName deviceConfig = new ComponentName("device", "config");
4692 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
4693 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
4694 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
4695 mService.getBinderService().clearData("device", 0, false);
4696 verify(mConditionProviders, times(1)).resetPackage(
4697 eq("device"), eq(0));
4698 }
4699
4700 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004701 public void testFlagBubble() throws RemoteException {
4702 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004703 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004704
4705 // Notif with bubble metadata but not our other misc requirements
4706 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4707 null /* tvExtender */, true /* isBubble */);
4708
4709 // Say we're foreground
4710 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4711 IMPORTANCE_FOREGROUND);
4712
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004713 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor65dcaa92019-04-03 12:21:44 -07004714 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4715 waitForIdle();
4716
4717 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4718 assertEquals(1, notifs.length);
4719 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4720 assertTrue(mService.getNotificationRecord(
4721 nr.sbn.getKey()).getNotification().isBubbleNotification());
4722 }
4723
4724 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004725 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4726 // Bubbles are allowed!
4727 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4728
4729 // Notif with bubble metadata but not our other misc requirements
4730 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4731 null /* tvExtender */, true /* isBubble */);
4732
4733 // Say we're foreground
4734 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4735 IMPORTANCE_FOREGROUND);
4736
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004737 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorc6820342019-05-20 12:04:36 -07004738 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4739 waitForIdle();
4740
4741 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4742 assertEquals(1, notifs.length);
4743 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4744 assertFalse(mService.getNotificationRecord(
4745 nr.sbn.getKey()).getNotification().isBubbleNotification());
4746 }
4747
4748 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004749 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004750 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004751 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004752
Mady Mellorbe797962019-04-01 16:04:24 -07004753 // Notif with bubble metadata but not our other misc requirements
4754 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4755 null /* tvExtender */, true /* isBubble */);
4756
4757 // Say we're foreground
4758 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4759 IMPORTANCE_FOREGROUND);
4760
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004761 mBinderService.enqueueNotificationWithTag(PKG, PKG,
4762 nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07004763 waitForIdle();
4764
4765 // yes allowed, yes foreground, yes bubble
4766 assertTrue(mService.getNotificationRecord(
4767 nr.sbn.getKey()).getNotification().isBubbleNotification());
4768 }
4769
4770 @Test
4771 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4772 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004773 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004774
4775 // Notif with bubble metadata but not our other misc requirements
4776 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4777 null /* tvExtender */, true /* isBubble */);
4778
4779 // Make sure we're NOT foreground
4780 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4781 IMPORTANCE_VISIBLE);
4782
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004783 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004784 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4785 waitForIdle();
4786
4787 // yes allowed but NOT foreground, no bubble
4788 assertFalse(mService.getNotificationRecord(
4789 nr.sbn.getKey()).getNotification().isBubbleNotification());
4790 }
4791
4792 @Test
4793 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4794 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004795 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004796
4797 // Notif with bubble metadata but not our other misc requirements
4798 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4799 null /* tvExtender */, true /* isBubble */);
4800
4801 // Send notif when we're foreground
4802 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4803 IMPORTANCE_FOREGROUND);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004804 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004805 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4806 waitForIdle();
4807
4808 // yes allowed, yes foreground, yes bubble
4809 assertTrue(mService.getNotificationRecord(
4810 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4811
4812 // Send a new update when we're not foreground
4813 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4814 null /* tvExtender */, true /* isBubble */);
4815
4816 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4817 IMPORTANCE_VISIBLE);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004818 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004819 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4820 waitForIdle();
4821
4822 // yes allowed, previously foreground / flagged, yes bubble
4823 assertTrue(mService.getNotificationRecord(
4824 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4825
4826 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4827 assertEquals(1, notifs2.length);
4828 assertEquals(1, mService.getNotificationRecordCount());
4829 }
4830
4831 @Test
4832 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4833 throws RemoteException {
4834 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004835 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004836
4837 // Notif with bubble metadata but not our other misc requirements
4838 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4839 null /* tvExtender */, true /* isBubble */);
4840
4841 // Send notif when we're foreground
4842 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4843 IMPORTANCE_FOREGROUND);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004844 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004845 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4846 waitForIdle();
4847
4848 // yes allowed, yes foreground, yes bubble
4849 assertTrue(mService.getNotificationRecord(
4850 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4851
4852 // Remove the bubble
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004853 mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), nr1.sbn.getId(),
Mady Mellorbe797962019-04-01 16:04:24 -07004854 nr1.sbn.getUserId());
4855 waitForIdle();
4856
4857 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4858 assertEquals(0, notifs.length);
4859 assertEquals(0, mService.getNotificationRecordCount());
4860
4861 // Send a new update when we're not foreground
4862 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4863 null /* tvExtender */, true /* isBubble */);
4864
4865 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4866 IMPORTANCE_VISIBLE);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004867 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004868 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4869 waitForIdle();
4870
4871 // yes allowed, but was removed & no foreground, so no bubble
4872 assertFalse(mService.getNotificationRecord(
4873 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4874
4875 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4876 assertEquals(1, notifs2.length);
4877 assertEquals(1, mService.getNotificationRecordCount());
4878 }
4879
4880 @Test
4881 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4882 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004883 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004884
4885 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004886 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004887 // Give it a person
4888 Person person = new Person.Builder()
4889 .setName("bubblebot")
4890 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004891 // It needs remote input to be bubble-able
4892 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4893 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4894 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4895 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4896 inputIntent).addRemoteInput(remoteInput)
4897 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004898 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004899 Notification.Builder nb = new Notification.Builder(mContext,
4900 mTestNotificationChannel.getId())
4901 .setContentTitle("foo")
4902 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004903 .setStyle(new Notification.MessagingStyle(person)
4904 .setConversationTitle("Bubble Chat")
4905 .addMessage("Hello?",
4906 SystemClock.currentThreadTimeMillis() - 300000, person)
4907 .addMessage("Is it me you're looking for?",
4908 SystemClock.currentThreadTimeMillis(), person)
4909 )
Mady Mellora10448e2019-04-26 13:50:58 -07004910 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -07004911 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4912
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004913 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4914 "testFlagBubbleNotifs_flag_messaging", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07004915 nb.build(), new UserHandle(mUid), null, 0);
4916 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4917
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004918 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004919 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4920 waitForIdle();
4921
4922 // yes allowed, yes messaging, yes bubble
4923 assertTrue(mService.getNotificationRecord(
4924 sbn.getKey()).getNotification().isBubbleNotification());
4925 }
4926
4927 @Test
4928 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4929 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004930 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004931
4932 // Give it bubble metadata
4933 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4934 // Give it a person
4935 Person person = new Person.Builder()
4936 .setName("bubblebot")
4937 .build();
4938 // Make it a phone call
4939 Notification.Builder nb = new Notification.Builder(mContext,
4940 mTestNotificationChannel.getId())
4941 .setCategory(CATEGORY_CALL)
4942 .addPerson(person)
4943 .setContentTitle("foo")
4944 .setBubbleMetadata(data)
4945 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4946
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004947 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4948 "testFlagBubbleNotifs_flag_phonecall", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07004949 nb.build(), new UserHandle(mUid), null, 0);
4950 // Make sure it has foreground service
4951 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4952 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4953
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004954 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004955 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4956 waitForIdle();
4957
4958 // yes phone call, yes person, yes foreground service, yes bubble
4959 assertTrue(mService.getNotificationRecord(
4960 sbn.getKey()).getNotification().isBubbleNotification());
4961 }
4962
4963 @Test
4964 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4965 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004966 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004967
4968 // Give it bubble metadata
4969 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4970 // Give it a person
4971 Person person = new Person.Builder()
4972 .setName("bubblebot")
4973 .build();
4974 // Make it a phone call
4975 Notification.Builder nb = new Notification.Builder(mContext,
4976 mTestNotificationChannel.getId())
4977 .setCategory(CATEGORY_CALL)
4978 .addPerson(person)
4979 .setContentTitle("foo")
4980 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004981 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4982
4983 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4984 nb.build(), new UserHandle(mUid), null, 0);
4985 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4986
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004987 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004988 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4989 waitForIdle();
4990
Mady Mellorbe797962019-04-01 16:04:24 -07004991 // yes phone call, yes person, NO foreground service, no bubble
4992 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004993 sbn.getKey()).getNotification().isBubbleNotification());
4994 }
4995
4996 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004997 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4998 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004999 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005000
5001 // Give it bubble metadata
5002 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
5003 // Make it a phone call
5004 Notification.Builder nb = new Notification.Builder(mContext,
5005 mTestNotificationChannel.getId())
5006 .setCategory(CATEGORY_CALL)
5007 .setContentTitle("foo")
5008 .setBubbleMetadata(data)
5009 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5010
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005011 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5012 "testFlagBubbleNotifs_noFlag_phonecall_noPerson", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005013 nb.build(), new UserHandle(mUid), null, 0);
5014 // Make sure it has foreground service
5015 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5016 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5017
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005018 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005019 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5020 waitForIdle();
5021
5022 // yes phone call, yes foreground service, BUT NO person, no bubble
5023 assertFalse(mService.getNotificationRecord(
5024 sbn.getKey()).getNotification().isBubbleNotification());
5025 }
5026
5027 @Test
5028 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
5029 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005030 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005031
5032 // Give it bubble metadata
5033 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
5034 // Give it a person
5035 Person person = new Person.Builder()
5036 .setName("bubblebot")
5037 .build();
5038 // No category
5039 Notification.Builder nb = new Notification.Builder(mContext,
5040 mTestNotificationChannel.getId())
5041 .addPerson(person)
5042 .setContentTitle("foo")
5043 .setBubbleMetadata(data)
5044 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5045
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005046 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5047 "testFlagBubbleNotifs_noFlag_phonecall_noCategory", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005048 nb.build(), new UserHandle(mUid), null, 0);
5049 // Make sure it has foreground service
5050 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5051 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5052
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005053 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005054 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5055 waitForIdle();
5056
5057 // yes person, yes foreground service, BUT NO call, no bubble
5058 assertFalse(mService.getNotificationRecord(
5059 sbn.getKey()).getNotification().isBubbleNotification());
5060 }
5061
5062 @Test
5063 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005064 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005065 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005066
Mady Mellorbe797962019-04-01 16:04:24 -07005067 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005068 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005069 // Give it a person
5070 Person person = new Person.Builder()
5071 .setName("bubblebot")
5072 .build();
5073 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005074 Notification.Builder nb = new Notification.Builder(mContext,
5075 mTestNotificationChannel.getId())
5076 .setContentTitle("foo")
5077 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07005078 .setStyle(new Notification.MessagingStyle(person)
5079 .setConversationTitle("Bubble Chat")
5080 .addMessage("Hello?",
5081 SystemClock.currentThreadTimeMillis() - 300000, person)
5082 .addMessage("Is it me you're looking for?",
5083 SystemClock.currentThreadTimeMillis(), person)
5084 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005085 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5086
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005087 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5088 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed", mUid, 0,
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005089 nb.build(), new UserHandle(mUid), null, 0);
5090 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5091
5092 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005093 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005094 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5095 waitForIdle();
5096
5097 // not allowed, no bubble
5098 assertFalse(mService.getNotificationRecord(
5099 sbn.getKey()).getNotification().isBubbleNotification());
5100 }
5101
5102 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005103 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005104 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005105 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005106
5107 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07005108 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005109
5110 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005111 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005112 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5113 waitForIdle();
5114
5115 // no bubble metadata, no bubble
5116 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07005117 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005118 }
5119
5120 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005121 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005122 // Bubbles are allowed except on this channel
5123 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005124
Mady Mellorbe797962019-04-01 16:04:24 -07005125 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005126 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005127 // Give it a person
5128 Person person = new Person.Builder()
5129 .setName("bubblebot")
5130 .build();
5131 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005132 Notification.Builder nb = new Notification.Builder(mContext,
5133 mTestNotificationChannel.getId())
5134 .setContentTitle("foo")
5135 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07005136 .setStyle(new Notification.MessagingStyle(person)
5137 .setConversationTitle("Bubble Chat")
5138 .addMessage("Hello?",
5139 SystemClock.currentThreadTimeMillis() - 300000, person)
5140 .addMessage("Is it me you're looking for?",
5141 SystemClock.currentThreadTimeMillis(), person)
5142 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005143 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5144
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005145 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5146 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed", mUid, 0,
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005147 nb.build(), new UserHandle(mUid), null, 0);
5148 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5149
5150 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005151 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005152 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5153 waitForIdle();
5154
5155 // channel not allowed, no bubble
5156 assertFalse(mService.getNotificationRecord(
5157 sbn.getKey()).getNotification().isBubbleNotification());
5158 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005159
Mady Mellor49b1bf12019-03-29 12:00:02 -07005160 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005161 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005162 // Bubbles are not allowed!
5163 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005164
5165 // Give it bubble metadata
5166 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
5167 // Give it a person
5168 Person person = new Person.Builder()
5169 .setName("bubblebot")
5170 .build();
5171 // Make it a phone call
5172 Notification.Builder nb = new Notification.Builder(mContext,
5173 mTestNotificationChannel.getId())
5174 .setCategory(CATEGORY_CALL)
5175 .addPerson(person)
5176 .setContentTitle("foo")
5177 .setBubbleMetadata(data)
5178 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5179
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005180 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5181 "testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005182 nb.build(), new UserHandle(mUid), null, 0);
5183 // Make sure it has foreground service
5184 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5185 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5186
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005187 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005188 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5189 waitForIdle();
5190
5191 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
5192 assertFalse(mService.getNotificationRecord(
5193 sbn.getKey()).getNotification().isBubbleNotification());
5194 }
5195
5196 @Test
5197 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005198 // Bubbles are allowed, but not on channel.
5199 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005200
5201 // Give it bubble metadata
5202 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
5203 // Give it a person
5204 Person person = new Person.Builder()
5205 .setName("bubblebot")
5206 .build();
5207 // Make it a phone call
5208 Notification.Builder nb = new Notification.Builder(mContext,
5209 mTestNotificationChannel.getId())
5210 .setCategory(CATEGORY_CALL)
5211 .addPerson(person)
5212 .setContentTitle("foo")
5213 .setBubbleMetadata(data)
5214 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5215
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005216 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5217 "testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005218 nb.build(), new UserHandle(mUid), null, 0);
5219 // Make sure it has foreground service
5220 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5221 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5222
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005223 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005224 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5225 waitForIdle();
5226
5227 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
5228 assertFalse(mService.getNotificationRecord(
5229 sbn.getKey()).getNotification().isBubbleNotification());
5230 }
5231
5232 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005233 public void testCancelAllNotifications_cancelsBubble() throws Exception {
5234 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5235 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
5236 mService.addNotification(nr);
5237
5238 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
5239 waitForIdle();
5240
5241 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5242 assertEquals(0, notifs.length);
5243 assertEquals(0, mService.getNotificationRecordCount());
5244 }
5245
5246 @Test
5247 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
5248 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5249 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5250
5251 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005252 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5253 "testAppCancelNotifications_cancelsBubbles",
Mady Mellor49b1bf12019-03-29 12:00:02 -07005254 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
5255 waitForIdle();
5256
5257 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5258 assertEquals(1, notifs.length);
5259 assertEquals(1, mService.getNotificationRecordCount());
5260
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005261 mBinderService.cancelNotificationWithTag(PKG, PKG,
5262 "testAppCancelNotifications_cancelsBubbles", nrBubble.sbn.getId(),
Mady Mellor49b1bf12019-03-29 12:00:02 -07005263 nrBubble.sbn.getUserId());
5264 waitForIdle();
5265
5266 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5267 assertEquals(0, notifs2.length);
5268 assertEquals(0, mService.getNotificationRecordCount());
5269 }
5270
5271 @Test
5272 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5273 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5274 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5275 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5276
5277 mService.addNotification(nrNormal);
5278 mService.addNotification(nrBubble);
5279
5280 mService.getBinderService().cancelNotificationsFromListener(null, null);
5281 waitForIdle();
5282
5283 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5284 assertEquals(1, notifs.length);
5285 assertEquals(1, mService.getNotificationRecordCount());
5286 }
5287
5288 @Test
5289 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
5290 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5291 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5292 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5293
5294 mService.addNotification(nrNormal);
5295 mService.addNotification(nrBubble);
5296
5297 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
5298 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5299 waitForIdle();
5300
5301 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5302 assertEquals(1, notifs.length);
5303 assertEquals(1, mService.getNotificationRecordCount());
5304 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005305
Julia Reynolds4214da92019-04-10 15:04:06 -04005306 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005307 public void testGetAllowedAssistantAdjustments() throws Exception {
5308 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005309 assertNotNull(capabilities);
5310
5311 for (int i = capabilities.size() - 1; i >= 0; i--) {
5312 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005313 mBinderService.disallowAssistantAdjustment(capability);
5314 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5315 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005316 assertNotNull(currentCapabilities);
5317 assertFalse(currentCapabilities.contains(capability));
5318 }
5319 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005320
Julia Reynolds4214da92019-04-10 15:04:06 -04005321 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005322 public void testAdjustRestrictedKey() throws Exception {
5323 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005324 mService.addNotification(r);
5325 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005326
5327 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5328 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5329
5330 Bundle signals = new Bundle();
5331 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5332 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
5333 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
5334 "", r.getUser().getIdentifier());
5335
5336 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5337 r.applyAdjustments();
5338
5339 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5340 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5341 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005342
Julia Reynolds4214da92019-04-10 15:04:06 -04005343 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005344 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005345 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5346 .thenReturn(true);
5347 mService.setZenHelper(mock(ZenModeHelper.class));
5348 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005349 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5350 boolean isEnabled = true;
5351 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5352 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5353
5354 try {
5355 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005356 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005357 } catch (IllegalArgumentException e) {
5358 // yay
5359 }
5360
5361 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5362 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5363 mBinderService.addAutomaticZenRule(rule);
5364
5365 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5366 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5367 mBinderService.addAutomaticZenRule(rule);
5368 }
5369
Julia Reynolds4214da92019-04-10 15:04:06 -04005370 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005371 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5372 try {
5373 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5374 mUid + UserHandle.PER_USER_RANGE);
5375 fail("Cannot call cross user without permission");
5376 } catch (SecurityException e) {
5377 // pass
5378 }
5379
5380 // cross user, with permission, no problem
5381 TestablePermissions perms = mContext.getTestablePermissions();
5382 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5383 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5384 mUid + UserHandle.PER_USER_RANGE);
5385 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005386
Julia Reynolds4214da92019-04-10 15:04:06 -04005387 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005388 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5389 try {
5390 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5391 mUid + UserHandle.PER_USER_RANGE);
5392 fail("Cannot call cross user without permission");
5393 } catch (SecurityException e) {
5394 // pass
5395 }
5396
5397 // cross user, with permission, no problem
5398 TestablePermissions perms = mContext.getTestablePermissions();
5399 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5400 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5401 mUid + UserHandle.PER_USER_RANGE);
5402 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005403
5404 @Test
5405 public void testNotificationBubbleChanged_false() throws Exception {
5406 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005407 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005408
5409 // Notif with bubble metadata but not our other misc requirements
5410 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5411 null /* tvExtender */, true /* isBubble */);
5412
5413 // Say we're foreground
5414 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5415 IMPORTANCE_FOREGROUND);
5416
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005417 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005418 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5419 waitForIdle();
5420
Mady Mellor66efd5e2019-05-15 13:38:11 -07005421 // Reset as this is called when the notif is first sent
5422 reset(mListeners);
5423
Mady Mellora54e9fa2019-04-18 13:26:18 -07005424 // First we were a bubble
5425 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5426 assertEquals(1, notifsBefore.length);
5427 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5428
5429 // Notify we're not a bubble
5430 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5431 waitForIdle();
5432
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005433 // Make sure we are not a bubble
5434 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5435 assertEquals(1, notifsAfter.length);
5436 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005437 }
5438
5439 @Test
5440 public void testNotificationBubbleChanged_true() throws Exception {
5441 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005442 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005443
5444 // Plain notification that has bubble metadata
5445 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5446 null /* tvExtender */, true /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005447 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005448 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5449 waitForIdle();
5450
5451 // Would be a normal notification because wouldn't have met requirements to bubble
5452 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5453 assertEquals(1, notifsBefore.length);
5454 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5455
5456 // Make the package foreground so that we're allowed to be a bubble
5457 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5458 IMPORTANCE_FOREGROUND);
5459
Mady Mellor66efd5e2019-05-15 13:38:11 -07005460 // Reset as this is called when the notif is first sent
5461 reset(mListeners);
5462
Mady Mellora54e9fa2019-04-18 13:26:18 -07005463 // Notify we are now a bubble
5464 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5465 waitForIdle();
5466
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005467 // Make sure we are a bubble
5468 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5469 assertEquals(1, notifsAfter.length);
5470 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005471 }
5472
5473 @Test
5474 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5475 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005476 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005477
5478 // Notif that is not a bubble
5479 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5480 null /* tvExtender */, true /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005481 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005482 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5483 waitForIdle();
5484
Mady Mellor66efd5e2019-05-15 13:38:11 -07005485 // Reset as this is called when the notif is first sent
5486 reset(mListeners);
5487
Mady Mellora54e9fa2019-04-18 13:26:18 -07005488 // Would be a normal notification because wouldn't have met requirements to bubble
5489 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5490 assertEquals(1, notifsBefore.length);
5491 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5492
5493 // Notify we are now a bubble
5494 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5495 waitForIdle();
5496
5497 // We still wouldn't be a bubble because the notification didn't meet requirements
5498 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5499 assertEquals(1, notifsAfter.length);
5500 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5501 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005502
5503 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005504 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
5505 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5506 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5507 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5508 waitForIdle();
5509
5510 // A notification exists for the given record
5511 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5512 assertEquals(1, notifsBefore.length);
5513
5514 reset(mPackageManager);
5515
5516 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5517
5518 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Aran Ink979c9762019-10-24 16:09:45 -04005519 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005520
5521 // Grant permission called for the UID of SystemUI under the target user ID
5522 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5523 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5524 eq(nr.sbn.getUserId()));
5525 }
5526
5527 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005528 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
5529 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5530 waitForIdle();
5531
5532 // No notifications exist for the given record
5533 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5534 assertEquals(0, notifsBefore.length);
5535
5536 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5537 int uid = 0; // sysui on primary user
5538
5539 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5540 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5541
5542 // Grant permission still called if no NotificationRecord exists for the given key
5543 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5544 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5545 eq(nr.sbn.getUserId()));
5546 }
5547
5548 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005549 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
5550 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5551 NotificationRecord nr =
5552 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
5553 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5554 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5555 waitForIdle();
5556
5557 // A notification exists for the given record
5558 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5559 assertEquals(1, notifsBefore.length);
5560
5561 reset(mPackageManager);
5562
5563 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5564
5565 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Aran Ink979c9762019-10-24 16:09:45 -04005566 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005567
5568 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5569 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5570 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5571 eq(UserHandle.USER_SYSTEM));
5572 }
5573
5574 @Test
5575 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
5576 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5577 int otherUserId = 11;
5578 NotificationRecord nr =
5579 generateNotificationRecord(mTestNotificationChannel, otherUserId);
5580 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5581 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5582 waitForIdle();
5583
5584 // A notification exists for the given record
5585 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5586 assertEquals(1, notifsBefore.length);
5587
5588 reset(mPackageManager);
5589
5590 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5591
5592 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04005593 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04005594 String sysuiPackage = "sysui";
5595 final String[] sysuiPackages = new String[] { sysuiPackage };
5596 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
5597
5598 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
5599 // time this is called
5600 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
5601 .thenReturn(otherUserUid);
5602
Aran Ink979c9762019-10-24 16:09:45 -04005603 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5604 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005605
5606 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5607 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5608 eq(otherUserUid), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5609 eq(otherUserId));
5610 }
5611
5612 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005613 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
5614 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5615 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005616
Aran Ink979c9762019-10-24 16:09:45 -04005617 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5618 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005619
Aran Ink979c9762019-10-24 16:09:45 -04005620 // create an inline record with two uris in it
5621 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5622 nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5623 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5624 nr.getKey(), uri2, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005625
Aran Ink979c9762019-10-24 16:09:45 -04005626 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5627 assertNotNull(record); // record exists
5628 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04005629
Aran Ink979c9762019-10-24 16:09:45 -04005630 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5631
5632 // permissionOwner destroyed
5633 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5634 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
5635 }
5636
5637
5638 @Test
5639 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
5640 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5641 reset(mPackageManager);
5642
5643 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5644
5645 // no permissionOwner destroyed
5646 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
5647 any(), eq(null), eq(~0), eq(nr.getUserId()));
5648 }
5649
5650 @Test
5651 public void testClearInlineReplyUriPermission_userAll() throws Exception {
5652 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5653 UserHandle.USER_ALL);
5654 reset(mPackageManager);
5655
5656 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5657 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
5658
5659 // create an inline record a uri in it
5660 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5661 nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5662
5663 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5664 assertNotNull(record); // record exists
5665
5666 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5667
5668 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
5669 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5670 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005671 }
5672
5673 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005674 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5675 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005676 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005677
5678 // Plain notification that has bubble metadata
5679 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5680 null /* tvExtender */, true /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005681 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005682 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5683 waitForIdle();
5684
5685 // Would be a normal notification because wouldn't have met requirements to bubble
5686 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5687 assertEquals(1, notifsBefore.length);
5688 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5689
5690 // Make the package foreground so that we're allowed to be a bubble
5691 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5692 IMPORTANCE_FOREGROUND);
5693
5694 // And we are low ram
5695 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5696
5697 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5698 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5699 assertEquals(1, notifsAfter.length);
5700 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005701 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04005702
5703 @Test
5704 public void testRemoveLargeRemoteViews() throws Exception {
5705 int removeSize = mContext.getResources().getInteger(
5706 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
5707
5708 RemoteViews rv = mock(RemoteViews.class);
5709 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
5710 when(rv.clone()).thenReturn(rv);
5711 RemoteViews rv1 = mock(RemoteViews.class);
5712 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
5713 when(rv1.clone()).thenReturn(rv1);
5714 RemoteViews rv2 = mock(RemoteViews.class);
5715 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
5716 when(rv2.clone()).thenReturn(rv2);
5717 RemoteViews rv3 = mock(RemoteViews.class);
5718 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
5719 when(rv3.clone()).thenReturn(rv3);
5720 RemoteViews rv4 = mock(RemoteViews.class);
5721 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
5722 when(rv4.clone()).thenReturn(rv4);
5723 // note: different!
5724 RemoteViews rv5 = mock(RemoteViews.class);
5725 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
5726 when(rv5.clone()).thenReturn(rv5);
5727
5728 Notification np = new Notification.Builder(mContext, "test")
5729 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5730 .setContentText("test")
5731 .setCustomContentView(rv)
5732 .setCustomBigContentView(rv1)
5733 .setCustomHeadsUpContentView(rv2)
5734 .build();
5735 Notification n = new Notification.Builder(mContext, "test")
5736 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5737 .setContentText("test")
5738 .setCustomContentView(rv3)
5739 .setCustomBigContentView(rv4)
5740 .setCustomHeadsUpContentView(rv5)
5741 .setPublicVersion(np)
5742 .build();
5743
5744 assertNotNull(np.contentView);
5745 assertNotNull(np.bigContentView);
5746 assertNotNull(np.headsUpContentView);
5747
5748 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
5749 assertNotNull(n.publicVersion.contentView);
5750 assertNotNull(n.publicVersion.bigContentView);
5751 assertNotNull(n.publicVersion.headsUpContentView);
5752
5753 mService.fixNotification(n, PKG, "tag", 9, 0);
5754
5755 assertNull(n.contentView);
5756 assertNull(n.bigContentView);
5757 assertNotNull(n.headsUpContentView);
5758 assertNull(n.publicVersion.contentView);
5759 assertNull(n.publicVersion.bigContentView);
5760 assertNull(n.publicVersion.headsUpContentView);
5761
5762 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
5763 }
Mady Mellor06b770c2019-08-29 18:01:00 -07005764
Mady Mellora7731962019-06-17 17:57:02 -07005765 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
5766 throws Exception {
5767 // Bubbles are allowed!
5768 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5769
5770 // Give it bubble metadata
5771 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5772 .setSuppressNotification(true)
5773 .setAutoExpandBubble(true).build();
5774 // Give it a person
5775 Person person = new Person.Builder()
5776 .setName("bubblebot")
5777 .build();
5778 // It needs remote input to be bubble-able
5779 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5780 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5781 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5782 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5783 inputIntent).addRemoteInput(remoteInput)
5784 .build();
5785 // Make it messaging style
5786 Notification.Builder nb = new Notification.Builder(mContext,
5787 mTestNotificationChannel.getId())
5788 .setContentTitle("foo")
5789 .setBubbleMetadata(data)
5790 .setStyle(new Notification.MessagingStyle(person)
5791 .setConversationTitle("Bubble Chat")
5792 .addMessage("Hello?",
5793 SystemClock.currentThreadTimeMillis() - 300000, person)
5794 .addMessage("Is it me you're looking for?",
5795 SystemClock.currentThreadTimeMillis(), person)
5796 )
5797 .setActions(replyAction)
5798 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5799
5800 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5801 nb.build(), new UserHandle(mUid), null, 0);
5802 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5803
5804 // Ensure we're not foreground
5805 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5806 IMPORTANCE_VISIBLE);
5807
5808 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5809 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5810 waitForIdle();
5811
5812 // yes allowed, yes messaging, yes bubble
5813 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5814 assertTrue(notif.isBubbleNotification());
5815
5816 // Our flags should have failed since we're not foreground
5817 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
5818 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
5819 }
5820
5821 @Test
5822 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
5823 throws RemoteException {
5824 // Bubbles are allowed!
5825 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5826
5827 // Give it bubble metadata
5828 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5829 .setSuppressNotification(true)
5830 .setAutoExpandBubble(true).build();
5831 // Give it a person
5832 Person person = new Person.Builder()
5833 .setName("bubblebot")
5834 .build();
5835 // It needs remote input to be bubble-able
5836 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5837 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5838 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5839 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5840 inputIntent).addRemoteInput(remoteInput)
5841 .build();
5842 // Make it messaging style
5843 Notification.Builder nb = new Notification.Builder(mContext,
5844 mTestNotificationChannel.getId())
5845 .setContentTitle("foo")
5846 .setBubbleMetadata(data)
5847 .setStyle(new Notification.MessagingStyle(person)
5848 .setConversationTitle("Bubble Chat")
5849 .addMessage("Hello?",
5850 SystemClock.currentThreadTimeMillis() - 300000, person)
5851 .addMessage("Is it me you're looking for?",
5852 SystemClock.currentThreadTimeMillis(), person)
5853 )
5854 .setActions(replyAction)
5855 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5856
5857 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5858 nb.build(), new UserHandle(mUid), null, 0);
5859 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5860
5861 // Ensure we are in the foreground
5862 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5863 IMPORTANCE_FOREGROUND);
5864
5865 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5866 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5867 waitForIdle();
5868
5869 // yes allowed, yes messaging, yes bubble
5870 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5871 assertTrue(notif.isBubbleNotification());
5872
5873 // Our flags should have failed since we are foreground
5874 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
5875 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
5876 }
Mady Mellor22f2f072019-04-18 13:26:18 -07005877
5878 @Test
5879 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
5880 throws Exception {
5881 // Bubbles are allowed!
5882 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5883
5884 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5885 true /* summaryAutoCancel */);
5886
5887 // Dismiss summary
5888 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5889 true);
5890 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(),
5891 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(),
5892 NotificationStats.DISMISSAL_SHADE,
5893 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
5894 waitForIdle();
5895
5896 // The bubble should still exist
5897 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5898 assertEquals(1, notifsAfter.length);
5899 }
5900
5901 @Test
5902 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
5903 throws Exception {
5904 // Bubbles are allowed!
5905 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5906
5907 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5908 true /* summaryAutoCancel */);
5909
5910 // Click summary
5911 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5912 true);
5913 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
5914 nrSummary.getKey(), nv);
5915 waitForIdle();
5916
5917 // The bubble should still exist
5918 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5919 assertEquals(1, notifsAfter.length);
5920 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04005921
5922 @Test
5923 public void testLoadDefaultApprovedServices_emptyResources() {
5924 TestableResources tr = mContext.getOrCreateTestableResources();
5925 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
5926 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
5927 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
5928 setDefaultAssistantInDeviceConfig("");
5929
5930 mService.loadDefaultApprovedServices(USER_SYSTEM);
5931
5932 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
5933 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
5934 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
5935 }
5936
5937 @Test
5938 public void testLoadDefaultApprovedServices_dnd() {
5939 TestableResources tr = mContext.getOrCreateTestableResources();
5940 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
5941 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
5942 .thenReturn(new ArraySet<>());
5943
5944 mService.loadDefaultApprovedServices(USER_SYSTEM);
5945
5946 verify(mConditionProviders, times(1)).addDefaultComponentOrPackage("test");
5947 }
5948
5949 // TODO: add tests for the rest of the non-empty cases
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005950}