blob: 2cf5eaefcc586d178374afe0ddc4906972374bb5 [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;
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800103import android.content.pm.LauncherApps;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500104import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500105import android.content.pm.ParceledListSlice;
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800106import android.content.pm.ShortcutInfo;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400107import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200108import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400109import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700110import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400111import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400112import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500113import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400114import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400115import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400116import android.os.IBinder;
Julia Reynolds0f767342019-12-18 09:11:55 -0500117import android.os.Parcel;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400118import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400119import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700120import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500121import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400122import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000123import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600124import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000125import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400126import android.service.notification.Adjustment;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400127import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400128import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500129import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400130import android.service.notification.ZenPolicy;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400131import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400132import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400133import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400134import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400135import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400136import android.testing.TestablePermissions;
Julia Reynolds57a974b2019-10-07 11:51:47 -0400137import android.testing.TestableResources;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400138import android.text.Html;
Julia Reynolds0f767342019-12-18 09:11:55 -0500139import android.text.TextUtils;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400140import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000141import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400142import android.util.AtomicFile;
Julia Reynolds469144c2019-06-21 14:30:28 -0400143import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400144import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400145
Mady Mellor49b1bf12019-03-29 12:00:02 -0700146import androidx.annotation.Nullable;
147import androidx.test.InstrumentationRegistry;
148
Kristian Monsen05f34792018-04-09 10:27:16 +0200149import com.android.internal.R;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000150import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Will Brockmancfd98302020-01-29 15:57:30 -0500151import com.android.internal.logging.InstanceIdSequence;
152import com.android.internal.logging.InstanceIdSequenceFake;
Julia Reynolds503ed942017-10-04 16:04:56 -0400153import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400154import com.android.internal.util.FastXmlSerializer;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700155import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400156import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500157import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400158import com.android.server.lights.LightsManager;
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100159import com.android.server.lights.LogicalLight;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400160import com.android.server.notification.NotificationManagerService.NotificationAssistants;
161import com.android.server.notification.NotificationManagerService.NotificationListeners;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700162import com.android.server.uri.UriGrantsManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400163import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400164
165import org.junit.After;
166import org.junit.Before;
167import org.junit.Test;
168import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500169import org.mockito.ArgumentCaptor;
170import org.mockito.Mock;
171import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400172import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400173import org.xmlpull.v1.XmlPullParser;
174import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500175
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400176import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400177import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400178import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400179import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400180import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400181import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400182import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500183import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000184import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400185import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400186import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200187import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500188
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400189
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400190@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400191@RunWith(AndroidTestingRunner.class)
192@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500193public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500194 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000195
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400196 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500197 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500198 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400199 private NotificationManagerInternal mInternalService;
Julia Reynoldsda781472017-04-12 09:41:16 -0400200 @Mock
201 private IPackageManager mPackageManager;
202 @Mock
203 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400204 @Mock
205 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400206 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500207 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400208 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400209 @Mock
210 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400211 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400212 AtomicFile mPolicyFile;
213 File mFile;
214 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400215 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400216 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400217 private UsageStatsManagerInternal mAppUsageStats;
218 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400219 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400220 @Mock
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800221 private LauncherApps mLauncherApps;
222 @Mock
Julia Reynolds68263d12017-06-21 14:21:19 -0400223 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200224 @Mock
225 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400226 @Mock
227 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400228
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500229 private static final int MAX_POST_DELAY = 1000;
230
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500231 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500232 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000233
234 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
235
Julia Reynoldsda781472017-04-12 09:41:16 -0400236 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400237 private NotificationListeners mListeners;
238 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400239 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400240 private ManagedServices.ManagedServiceInfo mListener;
241 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400242 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400243 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400244 @Mock
245 IBinder mPermOwner;
246 @Mock
247 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700248 @Mock
249 IUriGrantsManager mUgm;
250 @Mock
251 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400252 @Mock
253 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000254 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000255 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
256 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400257 @Mock
258 UserManager mUm;
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500259 @Mock
260 NotificationHistoryManager mHistoryManager;
Will Brockman2b6959e2020-01-22 09:59:50 -0500261 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
Will Brockmancfd98302020-01-29 15:57:30 -0500262 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
263 1 << 30);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500264
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400265 // Use a Testable subclass so we can simulate calls from the system without failing.
266 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500267 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700268 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000269 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000270 @Nullable
271 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500272
Will Brockmancfd98302020-01-29 15:57:30 -0500273 TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
274 InstanceIdSequence notificationInstanceIdSequence) {
275 super(context, logger, notificationInstanceIdSequence);
Amith Yamasani803eab692017-11-09 17:47:04 -0800276 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400277
278 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400279 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500280 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700281 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400282 }
283
284 @Override
285 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500286 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700287 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400288 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400289
290 @Override
291 protected ICompanionDeviceManager getCompanionManager() {
292 return null;
293 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800294
295 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800296 protected void reportUserInteraction(NotificationRecord r) {
297 return;
298 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500299
300 @Override
301 protected void handleSavePolicyFile() {
302 return;
303 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000304
305 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000306 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
307 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000308 countLogSmartSuggestionsVisible++;
309 }
310
Annie Meng8b646fd2019-02-01 18:46:42 +0000311 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000312 protected void setNotificationAssistantAccessGrantedForUserInternal(
313 ComponentName assistant, int userId, boolean granted) {
314 if (mNotificationAssistantAccessGrantedCallback != null) {
315 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
316 return;
317 }
318 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
319 }
320
321 private void setNotificationAssistantAccessGrantedCallback(
322 @Nullable NotificationAssistantAccessGrantedCallback callback) {
323 this.mNotificationAssistantAccessGrantedCallback = callback;
324 }
325
326 interface NotificationAssistantAccessGrantedCallback {
327 void onGranted(ComponentName assistant, int userId, boolean granted);
328 }
329
Mady Mellorca0c24c2019-05-16 16:14:32 -0700330 @Override
331 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
332 String packageName) {
333 // Tests for this not being true are in CTS NotificationManagerTest
334 return true;
335 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400336 }
337
Beverly58b24532018-10-02 09:08:23 -0400338 private class TestableToastCallback extends ITransientNotification.Stub {
339 @Override
340 public void show(IBinder windowToken) {
341 }
342
343 @Override
344 public void hide() {
345 }
346 }
347
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500348 @Before
349 public void setUp() throws Exception {
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000350 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
351 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
352
Julia Reynoldsda781472017-04-12 09:41:16 -0400353 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400354
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700355 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
356 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400357 LocalServices.removeServiceForTest(WindowManagerInternal.class);
358 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700359
Julia Reynolds4afe2642019-05-01 08:42:24 -0400360 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
361
Will Brockmancfd98302020-01-29 15:57:30 -0500362 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
363 mNotificationInstanceIdSequence);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500364
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400365 // Use this testable looper.
366 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500367 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400368 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400369
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400370 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400371 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
372 Object[] args = invocation.getArguments();
373 return getApplicationInfo((String) args[0], mUid);
374 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500375 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400376 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
377 Object[] args = invocation.getArguments();
378 return getApplicationInfo((String) args[0], mUid);
379 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400380 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500381 final LightsManager mockLightsManager = mock(LightsManager.class);
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100382 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400383 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400384 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700385 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400386 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400387 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400388 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500389
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400390 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400391 mFile = new File(mContext.getCacheDir(), "test.xml");
392 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400393 final String preupgradeXml = "<notification-policy></notification-policy>";
394 mPolicyFile = new AtomicFile(mFile);
395 FileOutputStream fos = mPolicyFile.startWrite();
396 fos.write(preupgradeXml.getBytes());
397 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400398
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400399 // Setup managed services
400 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400401 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400402 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
403 ArraySet<ComponentName> components = new ArraySet<>();
404 components.add(defaultComponent);
405 when(mListeners.getDefaultComponents()).thenReturn(components);
406 when(mConditionProviders.getDefaultPackages())
407 .thenReturn(new ArraySet<>(Arrays.asList("config")));
408 when(mAssistants.getDefaultComponents()).thenReturn(components);
409 when(mAssistants.queryPackageForServices(
410 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400411 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
412 ManagedServices.Config listenerConfig = new ManagedServices.Config();
413 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
414 when(mListeners.getConfig()).thenReturn(listenerConfig);
415 ManagedServices.Config assistantConfig = new ManagedServices.Config();
416 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
417 when(mAssistants.getConfig()).thenReturn(assistantConfig);
418 ManagedServices.Config dndConfig = new ManagedServices.Config();
419 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
420 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
421
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400422 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
423
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500424 mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
425 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400426 mListeners, mAssistants, mConditionProviders,
427 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
428 mGroupHelper, mAm, mAppUsageStats,
429 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500430 mAppOpsManager, mUm, mHistoryManager);
Julia Reynolds4afe2642019-05-01 08:42:24 -0400431 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
432
Julia Reynolds503ed942017-10-04 16:04:56 -0400433 mService.setAudioManager(mAudioManager);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800434 mService.setLauncherApps(mLauncherApps);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500435
436 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400437 mBinderService = mService.getBinderService();
438 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500439
440 mBinderService.createNotificationChannels(
441 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400442 assertNotNull(mBinderService.getNotificationChannel(
443 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400444 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500445 }
446
Julia Reynoldsb852e562017-06-06 16:14:18 -0400447 @After
448 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400449 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000450 clearDeviceConfig();
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500451 mService.unregisterDeviceConfigChange();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000452 InstrumentationRegistry.getInstrumentation()
453 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400454 }
455
Jay Aliomer4204f252019-08-26 11:36:53 -0400456 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
457 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
458 changed.put(true, new ArrayList<>());
459 changed.put(false, new ArrayList<>());
460 return changed;
461 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400462 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
463 final ApplicationInfo applicationInfo = new ApplicationInfo();
464 applicationInfo.uid = uid;
465 switch (pkg) {
466 case PKG_N_MR1:
467 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
468 break;
469 case PKG_O:
470 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
471 break;
472 case PKG_P:
473 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
474 break;
475 default:
476 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
477 break;
478 }
479 return applicationInfo;
480 }
481
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500482 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400483 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500484 }
485
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500486 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
487 boolean pkgEnabled, boolean channelEnabled) {
488 Settings.Global.putInt(mContext.getContentResolver(),
489 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
490 mService.mPreferencesHelper.updateBubblesEnabled();
491 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled());
492 try {
493 mBinderService.setBubblesAllowed(pkg, uid, pkgEnabled);
494 } catch (RemoteException e) {
495 e.printStackTrace();
496 }
Mady Mellorc6820342019-05-20 12:04:36 -0700497 mTestNotificationChannel.setAllowBubbles(channelEnabled);
498 }
499
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500500 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
501 Notification.Builder nb = new Notification.Builder(mContext, "a")
502 .setContentTitle("foo")
503 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400504 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
505 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500506 nb.build(), new UserHandle(userId), null, postTime);
507 return sbn;
508 }
509
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400510 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
511 String groupKey, boolean isSummary) {
512 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
513 .setContentTitle("foo")
514 .setSmallIcon(android.R.drawable.sym_def_app_icon)
515 .setGroup(groupKey)
516 .setGroupSummary(isSummary);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400517 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
518 "tag" + System.currentTimeMillis(), mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400519 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000520 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400521 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400522
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500523 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500524 return generateNotificationRecord(channel, null);
525 }
526
527 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
528 Notification.TvExtender extender) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500529 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500530 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500531 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500532 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500533 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500534 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500535 if (extender != null) {
536 nb.extend(extender);
537 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400538 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400539 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000540 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500541 }
542
Aran Inkfd2bfd32019-10-04 16:30:01 -0400543 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
544 if (channel == null) {
545 channel = mTestNotificationChannel;
546 }
547 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
548 .setContentTitle("foo")
549 .setSmallIcon(android.R.drawable.sym_def_app_icon);
550 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
551 nb.build(), new UserHandle(userId), null, 0);
552 return new NotificationRecord(mContext, sbn, channel);
553 }
554
Mady Mellor9e923e12019-12-17 16:08:46 -0800555 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
556 String tag) {
557 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
558 }
559
560 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
561 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
562 if (channel == null) {
563 channel = mTestNotificationChannel;
564 }
565 if (tag == null) {
566 tag = "tag";
567 }
568 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
569 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
570 tag, mUid, 0,
571 nb.build(), new UserHandle(mUid), null, 0);
572 return new NotificationRecord(mContext, sbn, channel);
573 }
574
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400575 private Map<String, Answer> getSignalExtractorSideEffects() {
576 Map<String, Answer> answers = new ArrayMap<>();
577
578 answers.put("override group key", invocationOnMock -> {
579 ((NotificationRecord) invocationOnMock.getArguments()[0])
580 .setOverrideGroupKey("bananas");
581 return null;
582 });
583 answers.put("override people", invocationOnMock -> {
584 ((NotificationRecord) invocationOnMock.getArguments()[0])
585 .setPeopleOverride(new ArrayList<>());
586 return null;
587 });
588 answers.put("snooze criteria", invocationOnMock -> {
589 ((NotificationRecord) invocationOnMock.getArguments()[0])
590 .setSnoozeCriteria(new ArrayList<>());
591 return null;
592 });
593 answers.put("notification channel", invocationOnMock -> {
594 ((NotificationRecord) invocationOnMock.getArguments()[0])
595 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
596 return null;
597 });
598 answers.put("badging", invocationOnMock -> {
599 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
600 r.setShowBadge(!r.canShowBadge());
601 return null;
602 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500603 answers.put("bubbles", invocationOnMock -> {
604 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
605 r.setAllowBubble(!r.canBubble());
606 return null;
607 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400608 answers.put("package visibility", invocationOnMock -> {
609 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
610 Notification.VISIBILITY_SECRET);
611 return null;
612 });
613
614 return answers;
615 }
616
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400617 private void clearDeviceConfig() {
618 DeviceConfig.resetToDefaults(
619 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
620 }
621
622 private void setDefaultAssistantInDeviceConfig(String componentName) {
623 DeviceConfig.setProperty(
624 DeviceConfig.NAMESPACE_SYSTEMUI,
625 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
626 componentName,
627 false);
628 }
629
Mady Mellor9e923e12019-12-17 16:08:46 -0800630 private Notification.BubbleMetadata.Builder getBubbleMetadataBuilder() {
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700631 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
632 return new Notification.BubbleMetadata.Builder()
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800633 .createIntentBubble(pi,
634 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700635 }
636
Mady Mellor9e923e12019-12-17 16:08:46 -0800637 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
638 String groupKey, boolean isSummary) {
639 // Give it a person
640 Person person = new Person.Builder()
641 .setName("bubblebot")
642 .build();
643 // It needs remote input to be bubble-able
644 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
645 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
646 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
647 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
648 inputIntent).addRemoteInput(remoteInput)
649 .build();
650 // Make it messaging style
651 Notification.Builder nb = new Notification.Builder(mContext,
652 mTestNotificationChannel.getId())
653 .setContentTitle("foo")
654 .setStyle(new Notification.MessagingStyle(person)
655 .setConversationTitle("Bubble Chat")
656 .addMessage("Hello?",
657 SystemClock.currentThreadTimeMillis() - 300000, person)
658 .addMessage("Is it me you're looking for?",
659 SystemClock.currentThreadTimeMillis(), person)
660 )
661 .setActions(replyAction)
662 .setSmallIcon(android.R.drawable.sym_def_app_icon)
663 .setGroupSummary(isSummary);
664 if (groupKey != null) {
665 nb.setGroup(groupKey);
666 }
667 if (addBubbleMetadata) {
668 nb.setBubbleMetadata(getBubbleMetadataBuilder().build());
669 }
670 return nb;
671 }
672
Mady Mellor22f2f072019-04-18 13:26:18 -0700673 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
674 throws RemoteException {
675
Mady Mellor9e923e12019-12-17 16:08:46 -0800676 String groupKey = "BUBBLE_GROUP";
Mady Mellor22f2f072019-04-18 13:26:18 -0700677
Mady Mellor9e923e12019-12-17 16:08:46 -0800678 // Notification that has bubble metadata
679 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
680 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
Mady Mellor22f2f072019-04-18 13:26:18 -0700681
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400682 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700683 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
684 waitForIdle();
685
686 // Make sure we are a bubble
687 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
688 assertEquals(1, notifsAfter.length);
689 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
690
Mady Mellor9e923e12019-12-17 16:08:46 -0800691 // Notification without bubble metadata
692 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
693 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
694
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400695 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700696 nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId());
697 waitForIdle();
698
699 notifsAfter = mBinderService.getActiveNotifications(PKG);
700 assertEquals(2, notifsAfter.length);
701
702 // Summary notification for both of those
Mady Mellor9e923e12019-12-17 16:08:46 -0800703 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
704 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
705
Mady Mellor22f2f072019-04-18 13:26:18 -0700706 if (summaryAutoCancel) {
707 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
708 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400709 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700710 nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId());
711 waitForIdle();
712
713 notifsAfter = mBinderService.getActiveNotifications(PKG);
714 assertEquals(3, notifsAfter.length);
715
716 return nrSummary;
717 }
718
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500719 @Test
Jay Aliomerfea80252019-11-20 18:14:24 -0500720 public void testDefaultAssistant_overrideDefault() {
721 final int userId = 0;
722 final String testComponent = "package/class";
723 final List<UserInfo> userInfos = new ArrayList<>();
724 userInfos.add(new UserInfo(0, "", 0));
725 final ArraySet<ComponentName> validAssistants = new ArraySet<>();
726 validAssistants.add(ComponentName.unflattenFromString(testComponent));
727 final String originalComponent = DeviceConfig.getProperty(
728 DeviceConfig.NAMESPACE_SYSTEMUI,
729 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE
730 );
731 DeviceConfig.setProperty(
732 DeviceConfig.NAMESPACE_SYSTEMUI,
733 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
734 testComponent,
735 false
736 );
737 when(mActivityManager.isLowRamDevice()).thenReturn(false);
738 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
739 .thenReturn(validAssistants);
740 when(mAssistants.getDefaultComponents()).thenReturn(new ArraySet<>());
741 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
742
743 mService.setDefaultAssistantForUser(userId);
744
745 verify(mAssistants).setPackageOrComponentEnabled(
746 eq(testComponent), eq(userId), eq(true), eq(true));
747
748 DeviceConfig.setProperty(
749 DeviceConfig.NAMESPACE_SYSTEMUI,
750 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
751 originalComponent,
752 false
753 );
754 }
755
756 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500757 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500758 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500759 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400760 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500761 new ParceledListSlice(Arrays.asList(channel)));
762 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400763 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500764 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500765 }
766
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500767 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500768 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500769 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400770 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200771 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500772 fail("Exception should be thrown immediately.");
773 } catch (NullPointerException e) {
774 // pass
775 }
776 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500777
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500778 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500779 public void testCreateNotificationChannels_TwoChannels() throws Exception {
780 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500781 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500782 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500783 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400784 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500785 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400786 assertTrue(mBinderService.getNotificationChannel(
787 PKG, mContext.getUserId(), PKG, "id1") != null);
788 assertTrue(mBinderService.getNotificationChannel(
789 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500790 }
791
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500792 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400793 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
794 throws Exception {
795 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500796 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400797 mBinderService.createNotificationChannels(PKG,
798 new ParceledListSlice(Arrays.asList(channel)));
799
800 // Recreating the channel doesn't throw, but ignores importance.
801 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400802 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400803 mBinderService.createNotificationChannels(PKG,
804 new ParceledListSlice(Arrays.asList(dupeChannel)));
805 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400806 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500807 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400808 }
809
810 @Test
811 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
812 throws Exception {
813 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500814 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400815 mBinderService.createNotificationChannels(PKG,
816 new ParceledListSlice(Arrays.asList(channel)));
817
818 // Recreating with a lower importance is allowed to modify the channel.
819 final NotificationChannel dupeChannel =
820 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
821 mBinderService.createNotificationChannels(PKG,
822 new ParceledListSlice(Arrays.asList(dupeChannel)));
823 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400824 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400825 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
826 }
827
828 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400829 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
830 throws Exception {
831 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500832 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400833 mBinderService.createNotificationChannels(PKG,
834 new ParceledListSlice(Arrays.asList(channel)));
835
836 // The user modifies importance directly, can no longer be changed by the app.
837 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400838 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400839 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
840
841 // Recreating with a lower importance leaves channel unchanged.
842 final NotificationChannel dupeChannel =
843 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
844 mBinderService.createNotificationChannels(PKG,
845 new ParceledListSlice(Arrays.asList(dupeChannel)));
846 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400847 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400848 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400849 }
850
851 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500852 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
853 throws Exception {
854 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500855 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500856 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400857 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400858 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500859 new ParceledListSlice(Arrays.asList(channel1, channel2)));
860 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400861 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500862 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500863 }
864
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500865 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500866 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500867 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
868
869 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400870 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500871 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400872
873 // isBlocked is only used for user blocking, not app suspension
874 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500875 }
876
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500877 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500878 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500879 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
880
881 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400882 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500883 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400884 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400885 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400886
887 mBinderService.createNotificationChannels(
888 PKG, new ParceledListSlice(Arrays.asList(channel)));
889 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400890 mBinderService.enqueueNotificationWithTag(PKG, PKG,
891 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400892 sbn.getId(), sbn.getNotification(), sbn.getUserId());
893 waitForIdle();
894 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
895 }
896
897 @Test
898 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
899 throws Exception {
900 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
901
902 NotificationChannel channel = new NotificationChannel("blocked", "name",
903 NotificationManager.IMPORTANCE_NONE);
904 mBinderService.createNotificationChannels(
905 PKG, new ParceledListSlice(Arrays.asList(channel)));
906
907 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400908 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400909 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400910 sbn.getId(), sbn.getNotification(), sbn.getUserId());
911 waitForIdle();
912 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
913 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400914 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400915 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
916 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400917 }
918
919 @Test
920 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
921 throws Exception {
922 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
923
924 NotificationChannel channel =
925 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
926 mBinderService.createNotificationChannels(
927 PKG, new ParceledListSlice(Arrays.asList(channel)));
928
929 NotificationChannel update =
930 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
931 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
932 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400933 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
934 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400935
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700936 StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400937 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400938 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400939 sbn.getId(), sbn.getNotification(), sbn.getUserId());
940 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700941 // The first time a foreground service notification is shown, we allow the channel
942 // to be updated to allow it to be seen.
943 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
944 assertEquals(IMPORTANCE_LOW,
945 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400946 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
947 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400948 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700949 waitForIdle();
950
951 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
952 update.setFgServiceShown(true);
953 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
954 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400955 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
956 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700957
958 sbn = generateNotificationRecord(channel).sbn;
959 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400960 mBinderService.enqueueNotificationWithTag(PKG, PKG,
961 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700962 sbn.getId(), sbn.getNotification(), sbn.getUserId());
963 waitForIdle();
964 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400965 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400966 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400967 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
968 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500969 }
970
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500971 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -0400972 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
973 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400974 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400975 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
976 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400977
978 NotificationChannel channel = new NotificationChannel("id", "name",
979 NotificationManager.IMPORTANCE_HIGH);
980 channel.setGroup("something");
981 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400982 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -0400983 verify(mUsageStats, times(1)).registerBlocked(eq(r));
984 }
985
986 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -0400987 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500988 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
989
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400990 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -0400991
992 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400993 mBinderService.enqueueNotificationWithTag(PKG, PKG,
994 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -0400995 sbn.getId(), sbn.getNotification(), sbn.getUserId());
996 waitForIdle();
997 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500998 }
999
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001000 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001001 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1002 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1003
1004 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1005
1006 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001007 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001008 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1009 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001010 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1011 waitForIdle();
1012 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001013 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001014 }
1015
Brad Stenning8c991ea2018-07-31 13:33:01 -07001016 /**
1017 * Confirm the system user on automotive devices can use car categories
1018 */
1019 @Test
1020 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
1021 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1022 .thenReturn(true);
1023 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1024 Notification.CATEGORY_CAR_WARNING,
1025 Notification.CATEGORY_CAR_INFORMATION);
1026 int id = 0;
1027 for (String category: categories) {
1028 final StatusBarNotification sbn =
1029 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
1030 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001031 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1032 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001033 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1034 }
1035 waitForIdle();
1036 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1037 }
1038
1039
1040 /**
1041 * Confirm restricted notification categories only apply to automotive.
1042 */
1043 @Test
1044 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1045 mService.isSystemUid = false;
1046 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1047 .thenReturn(false);
1048 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1049 Notification.CATEGORY_CAR_WARNING,
1050 Notification.CATEGORY_CAR_INFORMATION);
1051 int id = 0;
1052 for (String category: categories) {
1053 final StatusBarNotification sbn =
1054 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
1055 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001056 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1057 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001058 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1059 }
1060 waitForIdle();
1061 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1062 }
1063
1064 /**
1065 * Confirm if a non-system user tries to use the car categories on a automotive device that
1066 * they will get a security exception
1067 */
1068 @Test
1069 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1070 mService.isSystemUid = false;
1071 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1072 .thenReturn(true);
1073 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1074 Notification.CATEGORY_CAR_WARNING,
1075 Notification.CATEGORY_CAR_INFORMATION);
1076 for (String category: categories) {
1077 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1078 sbn.getNotification().category = category;
1079 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001080 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1081 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001082 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1083 fail("Calls from non system apps should not allow use of restricted categories");
1084 } catch (SecurityException e) {
1085 // pass
1086 }
1087 }
1088 waitForIdle();
1089 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1090 }
1091
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001092 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001093 public void testBlockedNotifications_blockedByAssistant() throws Exception {
1094 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001095 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001096
1097 NotificationChannel channel = new NotificationChannel("id", "name",
1098 NotificationManager.IMPORTANCE_HIGH);
1099 NotificationRecord r = generateNotificationRecord(channel);
1100 mService.addEnqueuedNotification(r);
1101
Julia Reynolds27c0a962018-12-10 12:37:28 -05001102 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001103 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001104 Adjustment adjustment = new Adjustment(
1105 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
1106 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001107
1108 NotificationManagerService.PostNotificationRunnable runnable =
1109 mService.new PostNotificationRunnable(r.getKey());
1110 runnable.run();
1111 waitForIdle();
1112
1113 verify(mUsageStats, never()).registerPostedByApp(any());
1114 }
1115
1116 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001117 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001118 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1119 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001120 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001121 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001122 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001123 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001124 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001125 }
1126
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001127 @Test
Will Brockman2b6959e2020-01-22 09:59:50 -05001128 public void testEnqueueNotificationWithTag_WritesExpectedLog() throws Exception {
1129 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1130 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1131 generateNotificationRecord(null).getNotification(), 0);
1132 waitForIdle();
1133 assertEquals(1, mNotificationRecordLogger.getCalls().size());
1134 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
1135 assertTrue(call.shouldLog());
1136 assertNotNull(call.r);
1137 assertNull(call.old);
1138 assertEquals(0, call.position);
1139 assertEquals(0, call.buzzBeepBlink);
1140 assertEquals(PKG, call.r.sbn.getPackageName());
1141 assertEquals(0, call.r.sbn.getId());
1142 assertEquals(tag, call.r.sbn.getTag());
Will Brockmancfd98302020-01-29 15:57:30 -05001143 assertNotNull(call.r.sbn.getInstanceId());
1144 assertEquals(0, call.r.sbn.getInstanceId().getId());
Will Brockman2b6959e2020-01-22 09:59:50 -05001145 }
1146
1147 @Test
1148 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1149 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1150 Notification original = new Notification.Builder(mContext,
1151 mTestNotificationChannel.getId())
1152 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1153 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1154 Notification update = new Notification.Builder(mContext,
1155 mTestNotificationChannel.getId())
1156 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1157 .setCategory(Notification.CATEGORY_ALARM).build();
1158 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1159 waitForIdle();
1160 assertEquals(2, mNotificationRecordLogger.getCalls().size());
Will Brockmancfd98302020-01-29 15:57:30 -05001161
Will Brockman2b6959e2020-01-22 09:59:50 -05001162 assertTrue(mNotificationRecordLogger.get(0).shouldLog());
1163 assertEquals(
1164 NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
1165 mNotificationRecordLogger.get(0).getUiEvent());
Will Brockmancfd98302020-01-29 15:57:30 -05001166 assertEquals(0, mNotificationRecordLogger.get(0).r.sbn.getInstanceId().getId());
1167
1168 assertTrue(mNotificationRecordLogger.get(1).shouldLog());
Will Brockman2b6959e2020-01-22 09:59:50 -05001169 assertEquals(
1170 NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_UPDATED,
1171 mNotificationRecordLogger.get(1).getUiEvent());
Will Brockmancfd98302020-01-29 15:57:30 -05001172 // Instance ID doesn't change on update of an active notification
1173 assertEquals(0, mNotificationRecordLogger.get(1).r.sbn.getInstanceId().getId());
Will Brockman2b6959e2020-01-22 09:59:50 -05001174 }
1175
1176 @Test
1177 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdates() throws Exception {
1178 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdates";
1179 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1180 generateNotificationRecord(null).getNotification(), 0);
1181 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1182 generateNotificationRecord(null).getNotification(), 0);
1183 waitForIdle();
1184 assertEquals(2, mNotificationRecordLogger.getCalls().size());
1185 assertTrue(mNotificationRecordLogger.get(0).shouldLog());
1186 assertFalse(mNotificationRecordLogger.get(1).shouldLog());
1187 }
1188
1189 @Test
Will Brockmancfd98302020-01-29 15:57:30 -05001190 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1191 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1192 Notification notification = new Notification.Builder(mContext,
1193 mTestNotificationChannel.getId())
1194 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1195 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1196 waitForIdle();
1197 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1198 waitForIdle();
1199 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1200 waitForIdle();
1201 assertEquals(2, mNotificationRecordLogger.getCalls().size());
1202
1203 assertTrue(mNotificationRecordLogger.get(0).shouldLog());
1204 assertEquals(
1205 NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
1206 mNotificationRecordLogger.get(0).getUiEvent());
1207 assertEquals(0, mNotificationRecordLogger.get(0).r.sbn.getInstanceId().getId());
1208
1209 assertTrue(mNotificationRecordLogger.get(1).shouldLog());
1210 assertEquals(
1211 NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
1212 mNotificationRecordLogger.get(1).getUiEvent());
1213 // New instance ID because notification was canceled before re-post
1214 assertEquals(1, mNotificationRecordLogger.get(1).r.sbn.getInstanceId().getId());
1215 }
1216
1217 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001218 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001219 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1220 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001221 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001222 mBinderService.cancelNotificationWithTag(PKG, PKG,
1223 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001224 waitForIdle();
1225 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001226 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001227 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001228 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001229 }
1230
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001231 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001232 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001233 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1234 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001235 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001236 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001237 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1238 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001239 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001240 mBinderService.cancelNotificationWithTag(PKG, PKG,
1241 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001242 waitForIdle();
1243 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001244 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001245 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001246 assertEquals(0, mService.getNotificationRecordCount());
1247 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1248 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1249 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001250 }
1251
1252 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001253 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001254 NotificationRecord r = generateNotificationRecord(null);
1255 final StatusBarNotification sbn = r.sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001256 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1257 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001258 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001259 mBinderService.cancelNotificationsFromListener(null, null);
1260 waitForIdle();
1261 StatusBarNotification[] notifs =
1262 mBinderService.getActiveNotifications(sbn.getPackageName());
1263 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001264 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001265 }
1266
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001267 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001268 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
1269 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001270 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1271 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001272 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001273 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001274 waitForIdle();
1275 StatusBarNotification[] notifs =
1276 mBinderService.getActiveNotifications(sbn.getPackageName());
1277 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001278 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001279 }
1280
1281 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001282 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1283 throws Exception {
1284 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1285 sbn.getNotification().flags =
1286 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1287 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1288 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1289 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1290 waitForIdle();
1291 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1292 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1293 }
1294
1295 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001296 public void testUserInitiatedClearAll_noLeak() throws Exception {
1297 final NotificationRecord n = generateNotificationRecord(
1298 mTestNotificationChannel, 1, "group", true);
1299
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001300 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1301 "testUserInitiatedClearAll_noLeak",
Julia Reynolds080361e2017-07-13 11:23:12 -04001302 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
1303 waitForIdle();
1304
Julia Reynolds503ed942017-10-04 16:04:56 -04001305 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001306 n.getUserId());
1307 waitForIdle();
1308 StatusBarNotification[] notifs =
1309 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1310 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001311 assertEquals(0, mService.getNotificationRecordCount());
1312 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1313 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1314 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001315 }
1316
1317 @Test
1318 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1319 final NotificationRecord parent = generateNotificationRecord(
1320 mTestNotificationChannel, 1, "group1", true);
1321 final NotificationRecord child = generateNotificationRecord(
1322 mTestNotificationChannel, 2, "group1", false);
1323
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001324 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1325 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds080361e2017-07-13 11:23:12 -04001326 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001327 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1328 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds080361e2017-07-13 11:23:12 -04001329 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1330 waitForIdle();
1331
1332 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1333 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001334 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001335 }
1336
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001337 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001338 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1339 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1340 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001341 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1342 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001343 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1344 }
1345 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1346 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001347
Julia Reynolds503ed942017-10-04 16:04:56 -04001348 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001349 }
1350
1351 @Test
1352 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1353 final NotificationRecord parent = generateNotificationRecord(
1354 mTestNotificationChannel, 1, "group1", true);
1355 final NotificationRecord parentAsChild = generateNotificationRecord(
1356 mTestNotificationChannel, 1, "group1", false);
1357 final NotificationRecord child = generateNotificationRecord(
1358 mTestNotificationChannel, 2, "group1", false);
1359
1360 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001361 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1362 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001363 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1364 waitForIdle();
1365
1366 // enqueue the child several times
1367 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001368 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1369 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001370 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1371 }
1372 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001373 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1374 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001375 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1376 parentAsChild.sbn.getUserId());
1377 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001378
Julia Reynolds503ed942017-10-04 16:04:56 -04001379 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001380 }
1381
1382 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001383 public void testAutobundledSummary_notificationAdded() {
1384 NotificationRecord summary =
1385 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1386 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1387 mService.addNotification(summary);
1388 mService.mSummaryByGroupKey.put("pkg", summary);
1389 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1390 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001391 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001392
1393 assertTrue(summary.sbn.isOngoing());
1394 }
1395
1396 @Test
1397 public void testAutobundledSummary_notificationRemoved() {
1398 NotificationRecord summary =
1399 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1400 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1401 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1402 mService.addNotification(summary);
1403 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1404 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1405 mService.mSummaryByGroupKey.put("pkg", summary);
1406
Mady Mellor6d775f82019-11-12 16:12:19 -08001407 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001408
1409 assertFalse(summary.sbn.isOngoing());
1410 }
1411
1412 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001413 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1414 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001415 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001416 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1417 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001418 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001419 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001420 waitForIdle();
1421 StatusBarNotification[] notifs =
1422 mBinderService.getActiveNotifications(sbn.getPackageName());
1423 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001424 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001425 }
1426
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001427 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001428 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1429 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001430 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001431 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1432 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001433 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001434 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1435 waitForIdle();
1436 StatusBarNotification[] notifs =
1437 mBinderService.getActiveNotifications(sbn.getPackageName());
1438 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001439 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001440 }
1441
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001442 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001443 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1444 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001445 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1446 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001447 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001448 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1449 waitForIdle();
1450 StatusBarNotification[] notifs =
1451 mBinderService.getActiveNotifications(sbn.getPackageName());
1452 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001453 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001454 }
1455
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001456 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001457 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1458 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001459 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1460 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001461 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001462 // Null pkg is how we signal a user switch.
1463 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1464 waitForIdle();
1465 StatusBarNotification[] notifs =
1466 mBinderService.getActiveNotifications(sbn.getPackageName());
1467 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001468 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001469 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001470
1471 @Test
Beverly40239d92017-07-07 10:20:41 -04001472 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1473 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1474 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001475 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1476 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001477 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1478 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1479 waitForIdle();
1480 StatusBarNotification[] notifs =
1481 mBinderService.getActiveNotifications(sbn.getPackageName());
1482 assertEquals(0, notifs.length);
1483 }
1484
1485 @Test
1486 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1487 final NotificationRecord notif = generateNotificationRecord(
1488 mTestNotificationChannel, 1, "group", true);
1489 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001490 mService.addNotification(notif);
1491 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001492 notif.getUserId(), 0, null);
1493 waitForIdle();
1494 StatusBarNotification[] notifs =
1495 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1496 assertEquals(0, notifs.length);
1497 }
1498
1499 @Test
1500 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1501 final NotificationRecord notif = generateNotificationRecord(
1502 mTestNotificationChannel, 1, "group", true);
1503 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001504 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001505
Julia Reynolds503ed942017-10-04 16:04:56 -04001506 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001507 notif.getUserId());
1508 waitForIdle();
1509 StatusBarNotification[] notifs =
1510 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1511 assertEquals(1, notifs.length);
1512 }
1513
1514 @Test
1515 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1516 final NotificationRecord parent = generateNotificationRecord(
1517 mTestNotificationChannel, 1, "group", true);
1518 final NotificationRecord child = generateNotificationRecord(
1519 mTestNotificationChannel, 2, "group", false);
1520 final NotificationRecord child2 = generateNotificationRecord(
1521 mTestNotificationChannel, 3, "group", false);
1522 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1523 final NotificationRecord newGroup = generateNotificationRecord(
1524 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001525 mService.addNotification(parent);
1526 mService.addNotification(child);
1527 mService.addNotification(child2);
1528 mService.addNotification(newGroup);
1529 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001530 waitForIdle();
1531 StatusBarNotification[] notifs =
1532 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1533 assertEquals(1, notifs.length);
1534 }
1535
1536 @Test
1537 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1538 final NotificationRecord parent = generateNotificationRecord(
1539 mTestNotificationChannel, 1, "group", true);
1540 final NotificationRecord child = generateNotificationRecord(
1541 mTestNotificationChannel, 2, "group", false);
1542 final NotificationRecord child2 = generateNotificationRecord(
1543 mTestNotificationChannel, 3, "group", false);
1544 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1545 final NotificationRecord newGroup = generateNotificationRecord(
1546 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001547 mService.addNotification(parent);
1548 mService.addNotification(child);
1549 mService.addNotification(child2);
1550 mService.addNotification(newGroup);
1551 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001552 parent.getUserId());
1553 waitForIdle();
1554 StatusBarNotification[] notifs =
1555 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1556 assertEquals(1, notifs.length);
1557 }
1558
1559 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001560 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001561 Notification n =
1562 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1563 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1564 .build();
1565 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
1566 n, new UserHandle(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001567 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001568 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001569 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001570 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1571 sbn.getUserId());
1572 waitForIdle();
1573 StatusBarNotification[] notifs =
1574 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001575 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001576 }
1577
1578 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001579 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1580 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1581 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001582 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001583 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001584 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1585 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001586 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001587 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001588 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1589 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001590 waitForIdle();
1591 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001592 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001593 }
1594
1595 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001596 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1597 throws Exception {
1598 final NotificationRecord parent = generateNotificationRecord(
1599 mTestNotificationChannel, 1, "group", true);
1600 final NotificationRecord child = generateNotificationRecord(
1601 mTestNotificationChannel, 2, "group", false);
1602 final NotificationRecord child2 = generateNotificationRecord(
1603 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001604 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001605 final NotificationRecord newGroup = generateNotificationRecord(
1606 mTestNotificationChannel, 4, "group2", false);
1607 mService.addNotification(parent);
1608 mService.addNotification(child);
1609 mService.addNotification(child2);
1610 mService.addNotification(newGroup);
1611 mService.getBinderService().cancelNotificationsFromListener(null, null);
1612 waitForIdle();
1613 StatusBarNotification[] notifs =
1614 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1615 assertEquals(0, notifs.length);
1616 }
1617
1618 @Test
1619 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1620 throws Exception {
1621 final NotificationRecord parent = generateNotificationRecord(
1622 mTestNotificationChannel, 1, "group", true);
1623 final NotificationRecord child = generateNotificationRecord(
1624 mTestNotificationChannel, 2, "group", false);
1625 final NotificationRecord child2 = generateNotificationRecord(
1626 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001627 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001628 final NotificationRecord newGroup = generateNotificationRecord(
1629 mTestNotificationChannel, 4, "group2", false);
1630 mService.addNotification(parent);
1631 mService.addNotification(child);
1632 mService.addNotification(child2);
1633 mService.addNotification(newGroup);
1634 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1635 child2.sbn.getKey(), newGroup.sbn.getKey()};
1636 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1637 waitForIdle();
1638 StatusBarNotification[] notifs =
1639 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1640 assertEquals(1, notifs.length);
1641 }
1642
1643 @Test
1644 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1645 final NotificationRecord parent = generateNotificationRecord(
1646 mTestNotificationChannel, 1, "group", true);
1647 final NotificationRecord child = generateNotificationRecord(
1648 mTestNotificationChannel, 2, "group", false);
1649 final NotificationRecord child2 = generateNotificationRecord(
1650 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001651 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001652 final NotificationRecord newGroup = generateNotificationRecord(
1653 mTestNotificationChannel, 4, "group2", false);
1654 mService.addNotification(parent);
1655 mService.addNotification(child);
1656 mService.addNotification(child2);
1657 mService.addNotification(newGroup);
1658 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1659 parent.getUserId());
1660 waitForIdle();
1661 StatusBarNotification[] notifs =
1662 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1663 assertEquals(0, notifs.length);
1664 }
1665
1666 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001667 public void testFindGroupNotificationsLocked() throws Exception {
1668 // make sure the same notification can be found in both lists and returned
1669 final NotificationRecord group1 = generateNotificationRecord(
1670 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001671 mService.addEnqueuedNotification(group1);
1672 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001673
1674 // should not be returned
1675 final NotificationRecord group2 = generateNotificationRecord(
1676 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001677 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001678 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1679 waitForIdle();
1680
1681 // should not be returned
1682 final NotificationRecord nonGroup = generateNotificationRecord(
1683 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001684 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001685 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1686 waitForIdle();
1687
1688 // same group, child, should be returned
1689 final NotificationRecord group1Child = generateNotificationRecord(
1690 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001691 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1692 group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001693 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1694 waitForIdle();
1695
1696 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001697 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001698 group1.sbn.getUserId());
1699 assertEquals(3, inGroup1.size());
1700 for (NotificationRecord record : inGroup1) {
1701 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1702 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1703 }
1704 }
1705
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001706 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001707 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1708 final NotificationRecord notif = generateNotificationRecord(
1709 mTestNotificationChannel, 1, "group", true);
1710 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1711 mService.addNotification(notif);
1712 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1713 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1714 waitForIdle();
1715 StatusBarNotification[] notifs =
1716 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1717 assertEquals(0, notifs.length);
1718 }
1719
1720 @Test
1721 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1722 throws Exception {
1723 final NotificationRecord parent = generateNotificationRecord(
1724 mTestNotificationChannel, 1, "group", true);
1725 final NotificationRecord child = generateNotificationRecord(
1726 mTestNotificationChannel, 2, "group", false);
1727 final NotificationRecord child2 = generateNotificationRecord(
1728 mTestNotificationChannel, 3, "group", false);
1729 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1730 final NotificationRecord newGroup = generateNotificationRecord(
1731 mTestNotificationChannel, 4, "group2", false);
1732 mService.addNotification(parent);
1733 mService.addNotification(child);
1734 mService.addNotification(child2);
1735 mService.addNotification(newGroup);
1736 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1737 child2.sbn.getKey(), newGroup.sbn.getKey()};
1738 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1739 waitForIdle();
1740 StatusBarNotification[] notifs =
1741 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1742 assertEquals(0, notifs.length);
1743 }
1744
1745 @Test
1746 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1747 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1748 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001749 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1750 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001751 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1752 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1753 waitForIdle();
1754 StatusBarNotification[] notifs =
1755 mBinderService.getActiveNotifications(sbn.getPackageName());
1756 assertEquals(0, notifs.length);
1757 }
1758
1759 @Test
1760 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1761 final NotificationRecord notif = generateNotificationRecord(
1762 mTestNotificationChannel, 1, "group", true);
1763 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1764 mService.addNotification(notif);
1765 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1766 notif.getUserId(), 0, null);
1767 waitForIdle();
1768 StatusBarNotification[] notifs =
1769 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1770 assertEquals(0, notifs.length);
1771 }
1772
1773 @Test
1774 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1775 final NotificationRecord notif = generateNotificationRecord(
1776 mTestNotificationChannel, 1, "group", true);
1777 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1778 mService.addNotification(notif);
1779
1780 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1781 notif.getUserId());
1782 waitForIdle();
1783 StatusBarNotification[] notifs =
1784 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1785 assertEquals(1, notifs.length);
1786 }
1787
1788 @Test
1789 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1790 final NotificationRecord parent = generateNotificationRecord(
1791 mTestNotificationChannel, 1, "group", true);
1792 final NotificationRecord child = generateNotificationRecord(
1793 mTestNotificationChannel, 2, "group", false);
1794 final NotificationRecord child2 = generateNotificationRecord(
1795 mTestNotificationChannel, 3, "group", false);
1796 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1797 final NotificationRecord newGroup = generateNotificationRecord(
1798 mTestNotificationChannel, 4, "group2", false);
1799 mService.addNotification(parent);
1800 mService.addNotification(child);
1801 mService.addNotification(child2);
1802 mService.addNotification(newGroup);
1803 mService.getBinderService().cancelNotificationsFromListener(null, null);
1804 waitForIdle();
1805 StatusBarNotification[] notifs =
1806 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1807 assertEquals(1, notifs.length);
1808 }
1809
1810 @Test
1811 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1812 throws Exception {
1813 final NotificationRecord parent = generateNotificationRecord(
1814 mTestNotificationChannel, 1, "group", true);
1815 final NotificationRecord child = generateNotificationRecord(
1816 mTestNotificationChannel, 2, "group", false);
1817 final NotificationRecord child2 = generateNotificationRecord(
1818 mTestNotificationChannel, 3, "group", false);
1819 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1820 final NotificationRecord newGroup = generateNotificationRecord(
1821 mTestNotificationChannel, 4, "group2", false);
1822 mService.addNotification(parent);
1823 mService.addNotification(child);
1824 mService.addNotification(child2);
1825 mService.addNotification(newGroup);
1826 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1827 child2.sbn.getKey(), newGroup.sbn.getKey()};
1828 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1829 waitForIdle();
1830 StatusBarNotification[] notifs =
1831 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1832 assertEquals(0, notifs.length);
1833 }
1834
1835 @Test
1836 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1837 final NotificationRecord parent = generateNotificationRecord(
1838 mTestNotificationChannel, 1, "group", true);
1839 final NotificationRecord child = generateNotificationRecord(
1840 mTestNotificationChannel, 2, "group", false);
1841 final NotificationRecord child2 = generateNotificationRecord(
1842 mTestNotificationChannel, 3, "group", false);
1843 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1844 final NotificationRecord newGroup = generateNotificationRecord(
1845 mTestNotificationChannel, 4, "group2", false);
1846 mService.addNotification(parent);
1847 mService.addNotification(child);
1848 mService.addNotification(child2);
1849 mService.addNotification(newGroup);
1850 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1851 parent.getUserId());
1852 waitForIdle();
1853 StatusBarNotification[] notifs =
1854 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1855 assertEquals(1, notifs.length);
1856 }
1857
1858 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001859 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001860 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001861 mService.setPreferencesHelper(mPreferencesHelper);
1862 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001863 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001864 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001865
Julia Reynoldsbad42972017-04-25 13:52:49 -04001866 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001867 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001868 generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05001869 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
1870 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001871 }
1872
1873 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001874 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001875 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001876 mService.setPreferencesHelper(mPreferencesHelper);
1877 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001878 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001879 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001880
Julia Reynoldsbad42972017-04-25 13:52:49 -04001881 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001882 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
1883 0, generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05001884 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
Julia Reynolds0f767342019-12-18 09:11:55 -05001885 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05001886 anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001887 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001888
1889 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001890 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001891 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001892
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001893 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001894 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1895 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1896
1897 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1898 captor.getValue().getAction());
1899 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001900 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1901 }
1902
1903 @Test
1904 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1905 mService.setPreferencesHelper(mPreferencesHelper);
1906
1907 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1908 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001909 }
1910
1911 @Test
1912 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001913 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001914
1915 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1916 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1917 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1918
1919 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1920 captor.getValue().getAction());
1921 assertEquals(PKG, captor.getValue().getPackage());
1922 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1923 }
1924
1925 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001926 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001927 mService.setPreferencesHelper(mPreferencesHelper);
1928 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001929 eq(mTestNotificationChannel.getId()), anyBoolean()))
1930 .thenReturn(mTestNotificationChannel);
1931
1932 NotificationChannel updatedChannel =
1933 new NotificationChannel(mTestNotificationChannel.getId(),
1934 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1935
1936 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1937 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1938 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1939
1940 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1941 captor.getValue().getAction());
1942 assertEquals(PKG, captor.getValue().getPackage());
1943 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001944 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001945 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1946 }
1947
1948 @Test
1949 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1950 NotificationChannel existingChannel =
1951 new NotificationChannel(mTestNotificationChannel.getId(),
1952 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001953 mService.setPreferencesHelper(mPreferencesHelper);
1954 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001955 eq(mTestNotificationChannel.getId()), anyBoolean()))
1956 .thenReturn(existingChannel);
1957
1958 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1959 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1960 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1961
1962 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1963 captor.getValue().getAction());
1964 assertEquals(PKG, captor.getValue().getPackage());
1965 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001966 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001967 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1968 }
1969
1970 @Test
1971 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1972 NotificationChannel existingChannel =
1973 new NotificationChannel(mTestNotificationChannel.getId(),
1974 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001975 mService.setPreferencesHelper(mPreferencesHelper);
1976 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001977 eq(mTestNotificationChannel.getId()), anyBoolean()))
1978 .thenReturn(existingChannel);
1979
1980 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1981 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1982 }
1983
1984 @Test
1985 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1986 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001987 mService.setPreferencesHelper(mPreferencesHelper);
1988 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001989 .thenReturn(existing);
1990
1991 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1992 updated.setBlocked(true);
1993
1994 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1995 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1996 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1997
1998 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1999 captor.getValue().getAction());
2000 assertEquals(PKG, captor.getValue().getPackage());
2001 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002002 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002003 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2004 }
2005
2006 @Test
2007 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
2008 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2009 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002010 mService.setPreferencesHelper(mPreferencesHelper);
2011 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002012 .thenReturn(existing);
2013
2014 mBinderService.updateNotificationChannelGroupForPackage(
2015 PKG, 0, new NotificationChannelGroup("id", "name"));
2016 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2017 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2018
2019 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2020 captor.getValue().getAction());
2021 assertEquals(PKG, captor.getValue().getPackage());
2022 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002023 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002024 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2025 }
2026
2027 @Test
2028 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
2029 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002030 mService.setPreferencesHelper(mPreferencesHelper);
2031 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002032 .thenReturn(existing);
2033
2034 mBinderService.updateNotificationChannelGroupForPackage(
2035 PKG, 0, new NotificationChannelGroup("id", "new name"));
2036 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2037 }
2038
2039 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002040 public void testCreateChannelNotifyListener() throws Exception {
2041 List<String> associations = new ArrayList<>();
2042 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002043 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002044 mService.setPreferencesHelper(mPreferencesHelper);
2045 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002046 eq(mTestNotificationChannel.getId()), anyBoolean()))
2047 .thenReturn(mTestNotificationChannel);
2048 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002049 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002050 eq(channel2.getId()), anyBoolean()))
2051 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002052 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
2053 eq(channel2), anyBoolean(), anyBoolean()))
2054 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002055
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002056 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002057 mBinderService.createNotificationChannels(PKG,
2058 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002059 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002060 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002061 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002062 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002063 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002064 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2065 }
2066
2067 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002068 public void testCreateChannelGroupNotifyListener() throws Exception {
2069 List<String> associations = new ArrayList<>();
2070 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002071 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002072 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002073 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
2074 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
2075
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002076 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002077 mBinderService.createNotificationChannelGroups(PKG,
2078 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002079 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002080 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002081 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002082 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002083 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002084 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2085 }
2086
2087 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002088 public void testUpdateChannelNotifyListener() throws Exception {
2089 List<String> associations = new ArrayList<>();
2090 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002091 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002092 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002093 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002094 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002095 eq(mTestNotificationChannel.getId()), anyBoolean()))
2096 .thenReturn(mTestNotificationChannel);
2097
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002098 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002099 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002100 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002101 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002102 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2103 }
2104
2105 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002106 public void testDeleteChannelNotifyListener() throws Exception {
2107 List<String> associations = new ArrayList<>();
2108 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002109 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002110 mService.setPreferencesHelper(mPreferencesHelper);
2111 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002112 eq(mTestNotificationChannel.getId()), anyBoolean()))
2113 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002114 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002115 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002116 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002117 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002118 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2119 }
2120
2121 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002122 public void testDeleteChannelGroupNotifyListener() throws Exception {
2123 List<String> associations = new ArrayList<>();
2124 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002125 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002126 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002127 mService.setPreferencesHelper(mPreferencesHelper);
2128 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002129 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002130 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002131 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002132 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002133 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002134 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2135 }
2136
2137 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002138 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002139 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002140 List<String> associations = new ArrayList<>();
2141 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002142 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002143 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002144 eq(mTestNotificationChannel.getId()), anyBoolean()))
2145 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002146
2147 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002148 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002149
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002150 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002151 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002152
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002153 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002154 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002155 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2156 }
2157
2158 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002159 public void testUpdateNotificationChannelFromPrivilegedListener_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 {
2165 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002166 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002167 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()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002173 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002174
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002175 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002176 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2177 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2178 }
2179
2180 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002181 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002182 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002183 List<String> associations = new ArrayList<>();
2184 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002185 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002186 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002187 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002188 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002189 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002190
2191 try {
2192 mBinderService.updateNotificationChannelFromPrivilegedListener(
2193 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2194 fail("incorrectly allowed a change to a user listener cannot see");
2195 } catch (SecurityException e) {
2196 // pass
2197 }
2198
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002199 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002200 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002201
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002202 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002203 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002204 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2205 }
2206
2207 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002208 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002209 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002210 List<String> associations = new ArrayList<>();
2211 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002212 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002213
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002214 mBinderService.getNotificationChannelsFromPrivilegedListener(
2215 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002216
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002217 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002218 anyString(), anyInt(), anyBoolean());
2219 }
2220
2221 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002222 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002223 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002224 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002225 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002226
2227 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002228 mBinderService.getNotificationChannelsFromPrivilegedListener(
2229 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002230 fail("listeners that don't have a companion device shouldn't be able to call this");
2231 } catch (SecurityException e) {
2232 // pass
2233 }
2234
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002235 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002236 anyString(), anyInt(), anyBoolean());
2237 }
2238
2239 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002240 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2241 throws Exception {
2242 mService.setPreferencesHelper(mPreferencesHelper);
2243 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2244 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2245
2246 mBinderService.getNotificationChannelsFromPrivilegedListener(
2247 null, PKG, Process.myUserHandle());
2248
2249 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2250 anyString(), anyInt(), anyBoolean());
2251 }
2252
2253 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002254 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2255 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002256 mService.setPreferencesHelper(mPreferencesHelper);
2257 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2258 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2259
2260 try {
2261 mBinderService.getNotificationChannelsFromPrivilegedListener(
2262 null, PKG, Process.myUserHandle());
2263 fail("listeners that don't have a companion device shouldn't be able to call this");
2264 } catch (SecurityException e) {
2265 // pass
2266 }
2267
2268 verify(mPreferencesHelper, never()).getNotificationChannels(
2269 anyString(), anyInt(), anyBoolean());
2270 }
2271
2272 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002273 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002274 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002275 List<String> associations = new ArrayList<>();
2276 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002277 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002278 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2279 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002280 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002281
2282 try {
2283 mBinderService.getNotificationChannelsFromPrivilegedListener(
2284 null, PKG, Process.myUserHandle());
2285 fail("listener getting channels from a user they cannot see");
2286 } catch (SecurityException e) {
2287 // pass
2288 }
2289
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002290 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002291 anyString(), anyInt(), anyBoolean());
2292 }
2293
2294 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002295 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002296 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002297 List<String> associations = new ArrayList<>();
2298 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002299 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002300
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002301 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2302 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002303
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002304 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002305 }
2306
2307 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002308 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002309 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002310 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002311 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002312
2313 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002314 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2315 null, PKG, Process.myUserHandle());
2316 fail("listeners that don't have a companion device shouldn't be able to call this");
2317 } catch (SecurityException e) {
2318 // pass
2319 }
2320
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002321 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002322 }
2323
2324 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002325 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002326 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002327 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002328 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002329 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2330 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002331 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002332 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002333 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2334 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002335 fail("listeners that don't have a companion device shouldn't be able to call this");
2336 } catch (SecurityException e) {
2337 // pass
2338 }
2339
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002340 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002341 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002342
2343 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002344 public void testHasCompanionDevice_failure() throws Exception {
2345 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2346 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002347 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002348 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002349
2350 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002351 public void testHasCompanionDevice_noService() {
Will Brockmancfd98302020-01-29 15:57:30 -05002352 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
2353 mNotificationInstanceIdSequence);
Julia Reynolds727a7282017-04-13 10:54:01 -04002354
Julia Reynolds503ed942017-10-04 16:04:56 -04002355 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002356 }
2357
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002358 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002359 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2360 final NotificationRecord notification = generateNotificationRecord(
2361 mTestNotificationChannel, 1, null, true);
2362 mService.addNotification(notification);
2363 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2364
2365 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2366 mService.new SnoozeNotificationRunnable(
2367 notification.getKey(), 100, null);
2368 snoozeNotificationRunnable.run();
2369 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2370 mService.new SnoozeNotificationRunnable(
2371 notification.getKey(), 100, null);
2372 snoozeNotificationRunnable.run();
2373
2374 // snooze twice
2375 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2376 }
2377
2378 @Test
2379 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2380 final NotificationRecord notification = generateNotificationRecord(
2381 mTestNotificationChannel, 1, "group", true);
2382 mService.addNotification(notification);
2383 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2384
2385 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2386 mService.new SnoozeNotificationRunnable(
2387 notification.getKey(), 100, null);
2388 snoozeNotificationRunnable.run();
2389 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2390 mService.new SnoozeNotificationRunnable(
2391 notification.getKey(), 100, null);
2392 snoozeNotificationRunnable.run();
2393
2394 // snooze twice
2395 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2396 }
2397
2398 @Test
2399 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2400 final NotificationRecord notification = generateNotificationRecord(
2401 mTestNotificationChannel, 1, "group", true);
2402 final NotificationRecord notification2 = generateNotificationRecord(
2403 mTestNotificationChannel, 2, "group", true);
2404 mService.addNotification(notification);
2405 mService.addNotification(notification2);
2406 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2407 when(mSnoozeHelper.getNotifications(
2408 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2409
2410 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2411 mService.new SnoozeNotificationRunnable(
2412 notification.getKey(), 100, null);
2413 snoozeNotificationRunnable.run();
2414 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2415 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2416 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2417 mService.new SnoozeNotificationRunnable(
2418 notification.getKey(), 100, null);
2419 snoozeNotificationRunnable.run();
2420
2421 // snooze twice
2422 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2423 }
2424
2425 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002426 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2427 final NotificationRecord nonGrouped = generateNotificationRecord(
2428 mTestNotificationChannel, 1, null, false);
2429 final NotificationRecord grouped = generateNotificationRecord(
2430 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002431 mService.addNotification(grouped);
2432 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002433
2434 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002435 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002436 nonGrouped.getKey(), 100, null);
2437 snoozeNotificationRunnable.run();
2438
2439 // only snooze the one notification
2440 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002441 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002442 }
2443
2444 @Test
2445 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2446 final NotificationRecord parent = generateNotificationRecord(
2447 mTestNotificationChannel, 1, "group", true);
2448 final NotificationRecord child = generateNotificationRecord(
2449 mTestNotificationChannel, 2, "group", false);
2450 final NotificationRecord child2 = generateNotificationRecord(
2451 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002452 mService.addNotification(parent);
2453 mService.addNotification(child);
2454 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002455
2456 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002457 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002458 parent.getKey(), 100, null);
2459 snoozeNotificationRunnable.run();
2460
2461 // snooze parent and children
2462 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2463 }
2464
2465 @Test
2466 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2467 final NotificationRecord parent = generateNotificationRecord(
2468 mTestNotificationChannel, 1, "group", true);
2469 final NotificationRecord child = generateNotificationRecord(
2470 mTestNotificationChannel, 2, "group", false);
2471 final NotificationRecord child2 = generateNotificationRecord(
2472 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002473 mService.addNotification(parent);
2474 mService.addNotification(child);
2475 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002476
2477 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002478 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002479 child2.getKey(), 100, null);
2480 snoozeNotificationRunnable.run();
2481
2482 // only snooze the one child
2483 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2484 }
2485
2486 @Test
2487 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2488 final NotificationRecord parent = generateNotificationRecord(
2489 mTestNotificationChannel, 1, "group", true);
2490 assertTrue(parent.sbn.getNotification().isGroupSummary());
2491 final NotificationRecord child = generateNotificationRecord(
2492 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002493 mService.addNotification(parent);
2494 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002495
2496 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002497 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002498 child.getKey(), 100, null);
2499 snoozeNotificationRunnable.run();
2500
2501 // snooze child and summary
2502 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2503 }
2504
2505 @Test
2506 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2507 final NotificationRecord child = generateNotificationRecord(
2508 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002509 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002510
2511 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002512 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002513 child.getKey(), 100, null);
2514 snoozeNotificationRunnable.run();
2515
2516 // snooze child only
2517 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2518 }
2519
2520 @Test
2521 public void testPostGroupChild_unsnoozeParent() throws Exception {
2522 final NotificationRecord child = generateNotificationRecord(
2523 mTestNotificationChannel, 2, "group", false);
2524
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002525 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002526 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2527 waitForIdle();
2528
2529 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2530 anyString(), anyInt(), eq(child.getGroupKey()));
2531 }
2532
2533 @Test
2534 public void testPostNonGroup_noUnsnoozing() throws Exception {
2535 final NotificationRecord record = generateNotificationRecord(
2536 mTestNotificationChannel, 2, null, false);
2537
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002538 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002539 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2540 waitForIdle();
2541
2542 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2543 }
2544
2545 @Test
2546 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2547 final NotificationRecord parent = generateNotificationRecord(
2548 mTestNotificationChannel, 2, "group", true);
2549
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002550 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002551 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2552 waitForIdle();
2553
2554 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2555 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002556
2557 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002558 public void testSetListenerAccessForUser() throws Exception {
2559 UserHandle user = UserHandle.of(10);
2560 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002561 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2562
Julia Reynolds92febc32017-10-26 11:30:31 -04002563
2564 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2565 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2566 c.flattenToString(), user.getIdentifier(), true, true);
2567 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2568 c.flattenToString(), user.getIdentifier(), false, true);
2569 verify(mAssistants, never()).setPackageOrComponentEnabled(
2570 any(), anyInt(), anyBoolean(), anyBoolean());
2571 }
2572
2573 @Test
2574 public void testSetAssistantAccessForUser() throws Exception {
2575 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002576 List<UserInfo> uis = new ArrayList<>();
2577 UserInfo ui = new UserInfo();
2578 ui.id = 10;
2579 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002580 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002581 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2582
2583 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002584
2585 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2586 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2587 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002588 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002589 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2590 c.flattenToString(), user.getIdentifier(), false, true);
2591 verify(mListeners, never()).setPackageOrComponentEnabled(
2592 any(), anyInt(), anyBoolean(), anyBoolean());
2593 }
2594
2595 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002596 public void testGetAssistantAllowedForUser() throws Exception {
2597 UserHandle user = UserHandle.of(10);
2598 try {
2599 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2600 } catch (IllegalStateException e) {
2601 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2602 throw e;
2603 }
2604 }
2605 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2606 }
2607
2608 @Test
2609 public void testGetAssistantAllowed() throws Exception {
2610 try {
2611 mBinderService.getAllowedNotificationAssistant();
2612 } catch (IllegalStateException e) {
2613 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2614 throw e;
2615 }
2616 }
2617 verify(mAssistants, times(1)).getAllowedComponents(0);
2618 }
2619
2620 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002621 public void testSetDndAccessForUser() throws Exception {
2622 UserHandle user = UserHandle.of(10);
2623 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002624 mBinderService.setNotificationPolicyAccessGrantedForUser(
2625 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002626
2627 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2628 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2629 c.getPackageName(), user.getIdentifier(), true, true);
2630 verify(mAssistants, never()).setPackageOrComponentEnabled(
2631 any(), anyInt(), anyBoolean(), anyBoolean());
2632 verify(mListeners, never()).setPackageOrComponentEnabled(
2633 any(), anyInt(), anyBoolean(), anyBoolean());
2634 }
2635
2636 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002637 public void testSetListenerAccess() throws Exception {
2638 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002639 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002640
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002641 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002642 c.flattenToString(), 0, true, true);
2643 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2644 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002645 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002646 any(), anyInt(), anyBoolean(), anyBoolean());
2647 }
2648
2649 @Test
2650 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002651 List<UserInfo> uis = new ArrayList<>();
2652 UserInfo ui = new UserInfo();
2653 ui.id = 0;
2654 uis.add(ui);
2655 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002656 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002657
2658 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002659
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002660 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002661 c.flattenToString(), 0, true, true);
2662 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2663 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002664 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002665 any(), anyInt(), anyBoolean(), anyBoolean());
2666 }
2667
2668 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002669 public void testSetAssistantAccess_multiProfile() throws Exception {
2670 List<UserInfo> uis = new ArrayList<>();
2671 UserInfo ui = new UserInfo();
2672 ui.id = 0;
2673 uis.add(ui);
2674 UserInfo ui10 = new UserInfo();
2675 ui10.id = 10;
2676 uis.add(ui10);
2677 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2678 ComponentName c = ComponentName.unflattenFromString("package/Component");
2679
2680 mBinderService.setNotificationAssistantAccessGranted(c, true);
2681
2682 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2683 c.flattenToString(), 0, true, true);
2684 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2685 c.flattenToString(), 10, true, true);
2686 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2687 c.flattenToString(), 0, false, true);
2688 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2689 c.flattenToString(), 10, false, true);
2690 verify(mListeners, never()).setPackageOrComponentEnabled(
2691 any(), anyInt(), anyBoolean(), anyBoolean());
2692 }
2693
2694 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002695 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2696 ArrayList<ComponentName> componentList = new ArrayList<>();
2697 ComponentName c = ComponentName.unflattenFromString("package/Component");
2698 componentList.add(c);
2699 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002700 List<UserInfo> uis = new ArrayList<>();
2701 UserInfo ui = new UserInfo();
2702 ui.id = 0;
2703 uis.add(ui);
2704 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002705
Julia Reynolds4afe2642019-05-01 08:42:24 -04002706 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002707
2708 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2709 c.flattenToString(), 0, true, false);
2710 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2711 c.flattenToString(), 0, false, false);
2712 verify(mListeners, never()).setPackageOrComponentEnabled(
2713 any(), anyInt(), anyBoolean(), anyBoolean());
2714 }
2715
2716 @Test
2717 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002718 List<UserInfo> uis = new ArrayList<>();
2719 UserInfo ui = new UserInfo();
2720 ui.id = 10;
2721 uis.add(ui);
2722 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002723 ArrayList<ComponentName> componentList = new ArrayList<>();
2724 ComponentName c = ComponentName.unflattenFromString("package/Component");
2725 componentList.add(c);
2726 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002727 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002728
Julia Reynolds4afe2642019-05-01 08:42:24 -04002729 mBinderService.setNotificationAssistantAccessGrantedForUser(
2730 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002731
2732 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2733 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002734 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002735 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2736 c.flattenToString(), user.getIdentifier(), false, false);
2737 verify(mListeners, never()).setPackageOrComponentEnabled(
2738 any(), anyInt(), anyBoolean(), anyBoolean());
2739 }
2740
2741 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002742 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2743 throws Exception {
2744 List<UserInfo> uis = new ArrayList<>();
2745 UserInfo ui = new UserInfo();
2746 ui.id = 0;
2747 uis.add(ui);
2748 UserInfo ui10 = new UserInfo();
2749 ui10.id = 10;
2750 uis.add(ui10);
2751 UserHandle user = ui.getUserHandle();
2752 ArrayList<ComponentName> componentList = new ArrayList<>();
2753 ComponentName c = ComponentName.unflattenFromString("package/Component");
2754 componentList.add(c);
2755 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2756 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2757
2758 mBinderService.setNotificationAssistantAccessGrantedForUser(
2759 null, user.getIdentifier(), true);
2760
2761 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2762 c.flattenToString(), user.getIdentifier(), true, false);
2763 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2764 c.flattenToString(), ui10.id, true, false);
2765 verify(mAssistants).setUserSet(0, true);
2766 verify(mAssistants).setUserSet(10, true);
2767 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2768 c.flattenToString(), user.getIdentifier(), false, false);
2769 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2770 c.flattenToString(), ui10.id, false, false);
2771 verify(mListeners, never()).setPackageOrComponentEnabled(
2772 any(), anyInt(), anyBoolean(), anyBoolean());
2773 }
2774
2775 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002776 public void testSetDndAccess() throws Exception {
2777 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002778
2779 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002780
2781 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2782 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002783 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002784 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002785 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002786 any(), anyInt(), anyBoolean(), anyBoolean());
2787 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002788
2789 @Test
2790 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2791 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2792 ComponentName c = ComponentName.unflattenFromString("package/Component");
2793 mBinderService.setNotificationListenerAccessGranted(c, true);
2794
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002795 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002796 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002797 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002798 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002799 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002800 any(), anyInt(), anyBoolean(), anyBoolean());
2801 }
2802
2803 @Test
2804 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2805 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2806 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002807 List<UserInfo> uis = new ArrayList<>();
2808 UserInfo ui = new UserInfo();
2809 ui.id = 0;
2810 uis.add(ui);
2811 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2812
Julia Reynolds68263d12017-06-21 14:21:19 -04002813 mBinderService.setNotificationAssistantAccessGranted(c, true);
2814
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002815 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002816 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002817 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002818 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002819 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002820 any(), anyInt(), anyBoolean(), anyBoolean());
2821 }
2822
2823 @Test
2824 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2825 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2826 ComponentName c = ComponentName.unflattenFromString("package/Component");
2827 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2828
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002829 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002830 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002831 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002832 anyString(), anyInt(), anyBoolean(), anyBoolean());
2833 verify(mAssistants, never()).setPackageOrComponentEnabled(
2834 any(), anyInt(), anyBoolean(), anyBoolean());
2835 }
2836
2837 @Test
2838 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2839 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2840 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2841 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002842
2843 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002844
2845 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2846 c.flattenToString(), 0, true, true);
2847 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002848 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002849 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002850 any(), anyInt(), anyBoolean(), anyBoolean());
2851 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002852
2853 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002854 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2855 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2856 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2857 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002858 List<UserInfo> uis = new ArrayList<>();
2859 UserInfo ui = new UserInfo();
2860 ui.id = 0;
2861 uis.add(ui);
2862 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2863
2864 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002865
2866 verify(mListeners, never()).setPackageOrComponentEnabled(
2867 anyString(), anyInt(), anyBoolean(), anyBoolean());
2868 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2869 c.flattenToString(), 0, false, true);
2870 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2871 c.flattenToString(), 0, true, true);
2872 }
2873
2874 @Test
2875 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2876 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2877 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2878 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002879
2880 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002881
2882 verify(mListeners, never()).setPackageOrComponentEnabled(
2883 anyString(), anyInt(), anyBoolean(), anyBoolean());
2884 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2885 c.getPackageName(), 0, true, true);
2886 verify(mAssistants, never()).setPackageOrComponentEnabled(
2887 any(), anyInt(), anyBoolean(), anyBoolean());
2888 }
2889
2890 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002891 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2892 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002893 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002894 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002895 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002896 runnable.run();
2897 waitForIdle();
2898
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002899 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002900 }
2901
2902 @Test
2903 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2904 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002905 NotificationRecord r =
2906 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002907 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002908
2909 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002910 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002911 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002912 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002913 runnable.run();
2914 waitForIdle();
2915
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002916 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002917 }
2918
2919 @Test
2920 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2921 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002922 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2923 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002924 mService.addNotification(r);
2925 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002926
2927 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002928 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002929 runnable.run();
2930 waitForIdle();
2931
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002932 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002933 }
Beverly40239d92017-07-07 10:20:41 -04002934
Julia Reynolds4db59552017-06-30 13:34:01 -04002935 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002936 public void testDontAutogroupIfCritical() throws Exception {
2937 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2938 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2939 mService.addEnqueuedNotification(r);
2940 NotificationManagerService.PostNotificationRunnable runnable =
2941 mService.new PostNotificationRunnable(r.getKey());
2942 runnable.run();
2943
2944 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2945 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2946 runnable = mService.new PostNotificationRunnable(r.getKey());
2947 mService.addEnqueuedNotification(r);
2948
2949 runnable.run();
2950 waitForIdle();
2951
2952 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2953 }
2954
2955 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002956 public void testNoFakeColorizedPermission() throws Exception {
2957 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2958 Notification.Builder nb = new Notification.Builder(mContext,
2959 mTestNotificationChannel.getId())
2960 .setContentTitle("foo")
2961 .setColorized(true)
2962 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2963 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002964 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
2965 "testNoFakeColorizedPermission", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002966 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002967 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2968
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002969 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds4db59552017-06-30 13:34:01 -04002970 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2971 waitForIdle();
2972
Julia Reynolds503ed942017-10-04 16:04:56 -04002973 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002974 PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04002975
2976 assertFalse(posted.getNotification().isColorized());
2977 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002978
2979 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002980 public void testGetNotificationCountLocked() {
2981 String sampleTagToExclude = null;
2982 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002983 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002984 NotificationRecord r =
2985 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002986 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002987
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002988 }
2989 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002990 NotificationRecord r =
2991 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002992 mService.addNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002993 sampleTagToExclude = r.sbn.getTag();
2994 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002995 }
2996
2997 // another package
2998 Notification n =
2999 new Notification.Builder(mContext, mTestNotificationChannel.getId())
3000 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3001 .build();
3002
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003003 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
3004 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003005 NotificationRecord otherPackage =
3006 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003007 mService.addEnqueuedNotification(otherPackage);
3008 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003009
3010 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003011 // anything that's currently enqueued or posted
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003012 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003013 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003014 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003015 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003016 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003017
3018 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003019 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04003020 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003021
3022 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003023 assertEquals(39, mService.getNotificationCountLocked(
3024 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003025 }
3026
3027 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04003028 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003029 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003030 mService.addNotification(r);
3031 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003032
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003033 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003034 }
3035
3036 @Test
3037 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003038 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3039 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003040 mService.addNotification(r);
3041 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003042
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003043 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003044 }
3045
3046 @Test
3047 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003048 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3049 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003050 mService.addNotification(r);
3051 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003052
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003053 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003054 }
3055
3056 @Test
3057 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04003058 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003059 NotificationManagerService.WorkerHandler handler = mock(
3060 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003061 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003062
3063 Map<String, Answer> answers = getSignalExtractorSideEffects();
3064 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04003065 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003066 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003067 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003068
3069 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
3070
Julia Reynolds503ed942017-10-04 16:04:56 -04003071 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003072 }
3073 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
3074 }
3075
3076 @Test
3077 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003078 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003079 NotificationManagerService.WorkerHandler handler = mock(
3080 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003081 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003082
3083 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003084 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003085
Julia Reynolds503ed942017-10-04 16:04:56 -04003086 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003087 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003088 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003089
3090 @Test
3091 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04003092 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003093 + "<ranking></ranking>"
3094 + "<enabled_listeners>"
3095 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3096 + "</enabled_listeners>"
3097 + "<enabled_assistants>"
3098 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3099 + "</enabled_assistants>"
3100 + "<dnd_apps>"
3101 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3102 + "</dnd_apps>"
3103 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003104 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003105 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3106 false,
3107 UserHandle.USER_ALL);
3108 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3109 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3110 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003111
3112 // numbers are inflated for setup
3113 verify(mListeners, times(1)).migrateToXml();
3114 verify(mConditionProviders, times(1)).migrateToXml();
3115 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003116 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003117 }
3118
3119 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003120 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
3121 final String upgradeXml = "<notification-policy version=\"1\">"
3122 + "<snoozed-notifications>></snoozed-notifications>"
3123 + "</notification-policy>";
3124 mService.readPolicyXml(
3125 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3126 false,
3127 UserHandle.USER_ALL);
3128 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class));
3129 }
3130
3131 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003132 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
3133 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003134 + "<ranking></ranking>"
3135 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003136 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003137 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
3138 false,
3139 UserHandle.USER_ALL);
3140 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
3141 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
3142 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003143
3144 // numbers are inflated for setup
3145 verify(mListeners, times(2)).migrateToXml();
3146 verify(mConditionProviders, times(2)).migrateToXml();
3147 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003148 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003149 }
3150
Annie Meng8b646fd2019-02-01 18:46:42 +00003151 @Test
3152 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3153 final String policyXml = "<notification-policy version=\"1\">"
3154 + "<ranking></ranking>"
3155 + "<enabled_listeners>"
3156 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3157 + "</enabled_listeners>"
3158 + "<enabled_assistants>"
3159 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3160 + "</enabled_assistants>"
3161 + "<dnd_apps>"
3162 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3163 + "</dnd_apps>"
3164 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003165 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00003166 mService.readPolicyXml(
3167 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3168 true,
3169 10);
3170 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3171 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3172 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3173 }
3174
3175 @Test
3176 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3177 final String policyXml = "<notification-policy version=\"1\">"
3178 + "<ranking></ranking>"
3179 + "<enabled_listeners>"
3180 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3181 + "</enabled_listeners>"
3182 + "<enabled_assistants>"
3183 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3184 + "</enabled_assistants>"
3185 + "<dnd_apps>"
3186 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3187 + "</dnd_apps>"
3188 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003189 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003190 mService.readPolicyXml(
3191 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3192 true,
3193 10);
3194 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3195 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3196 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3197 }
Beverlyd4f96492017-08-02 13:36:11 -04003198
3199 @Test
3200 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3201 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003202 mService.mZenModeHelper = mZenModeHelper;
3203 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003204 new Intent(Intent.ACTION_LOCALE_CHANGED));
3205
3206 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3207 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003208
3209 @Test
3210 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003211 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003212 final ApplicationInfo legacy = new ApplicationInfo();
3213 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3214 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3215 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003216 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3217 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003218 getContext().setMockPackageManager(mPackageManagerClient);
3219
3220 Notification.Builder nb = new Notification.Builder(mContext,
3221 NotificationChannel.DEFAULT_CHANNEL_ID)
3222 .setContentTitle("foo")
3223 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003224 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003225 .setPriority(Notification.PRIORITY_MIN);
3226
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003227 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3228 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003229 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003230
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003231 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3232 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003233 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003234
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003235 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003236 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003237
3238 nb = new Notification.Builder(mContext)
3239 .setContentTitle("foo")
3240 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003241 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003242 .setPriority(Notification.PRIORITY_MIN);
3243
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003244 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3245 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003246 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003247
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003248 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3249 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003250 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3251 waitForIdle();
3252 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003253 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003254
3255 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003256 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003257 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3258 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003259
3260 @Test
3261 public void testStats_updatedOnDirectReply() throws Exception {
3262 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3263 mService.addNotification(r);
3264
3265 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3266 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00003267 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04003268 }
3269
3270 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003271 public void testStats_updatedOnUserExpansion() throws Exception {
3272 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003273 mService.addNotification(r);
3274
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003275 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3276 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00003277 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003278 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003279
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003280 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3281 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00003282 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003283 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3284 }
3285
3286 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003287 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3288 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3289 mService.addNotification(r);
3290
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003291 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3292 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003293 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003294 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
3295
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003296 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3297 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003298 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003299 verify(mAssistants).notifyAssistantExpansionChangedLocked(
3300 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003301 }
3302
3303 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003304 public void testStats_updatedOnViewSettings() throws Exception {
3305 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3306 mService.addNotification(r);
3307
3308 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3309 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3310 }
3311
3312 @Test
3313 public void testStats_updatedOnVisibilityChanged() throws Exception {
3314 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3315 mService.addNotification(r);
3316
Dieter Hsud39f0d52018-04-14 02:08:30 +08003317 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003318 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3319 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
Alex Mang509e5542020-01-03 13:06:40 -08003320 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.sbn), eq(true));
Julia Reynolds503ed942017-10-04 16:04:56 -04003321 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3322 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3323 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
Alex Mang509e5542020-01-03 13:06:40 -08003324 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.sbn), eq(false));
Julia Reynolds503ed942017-10-04 16:04:56 -04003325 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3326 }
3327
3328 @Test
3329 public void testStats_dismissalSurface() throws Exception {
3330 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3331 mService.addNotification(r);
3332
Dieter Hsud39f0d52018-04-14 02:08:30 +08003333 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003334 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003335 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3336 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003337 waitForIdle();
3338
3339 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
3340 }
3341
3342 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003343 public void testStats_dismissalSentiment() throws Exception {
3344 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3345 mService.addNotification(r);
3346
3347 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
3348 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
3349 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3350 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3351 waitForIdle();
3352
3353 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3354 r.getStats().getDismissalSentiment());
3355 }
3356
3357 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003358 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003359 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3360 mService.addNotification(r);
3361 NotificationManagerService.WorkerHandler handler = mock(
3362 NotificationManagerService.WorkerHandler.class);
3363 mService.setHandler(handler);
3364
Julia Reynolds70aaea72018-07-13 13:38:34 -04003365 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3366
Julia Reynolds503ed942017-10-04 16:04:56 -04003367 Bundle signals = new Bundle();
3368 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003369 USER_SENTIMENT_NEGATIVE);
3370 Adjustment adjustment = new Adjustment(
3371 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3372 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3373
3374 waitForIdle();
3375
3376 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3377 }
3378
3379 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003380 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003381 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3382 mService.addNotification(r);
3383 NotificationManagerService.WorkerHandler handler = mock(
3384 NotificationManagerService.WorkerHandler.class);
3385 mService.setHandler(handler);
3386
3387 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003388 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003389 Adjustment adjustment = new Adjustment(
3390 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3391 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3392 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3393
3394 waitForIdle();
3395
3396 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3397 verify(handler, times(1)).scheduleCancelNotification(any());
3398 }
3399
3400 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003401 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3402 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3403 mService.addEnqueuedNotification(r);
3404 NotificationManagerService.WorkerHandler handler = mock(
3405 NotificationManagerService.WorkerHandler.class);
3406 mService.setHandler(handler);
3407 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3408
3409 Bundle signals = new Bundle();
3410 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3411 USER_SENTIMENT_NEGATIVE);
3412 Adjustment adjustment = new Adjustment(
3413 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3414 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3415
3416 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3417 }
3418
3419 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003420 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003421 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3422 mService.addEnqueuedNotification(r);
3423 NotificationManagerService.WorkerHandler handler = mock(
3424 NotificationManagerService.WorkerHandler.class);
3425 mService.setHandler(handler);
3426 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3427
3428 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003429 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003430 Adjustment adjustment = new Adjustment(
3431 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3432 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3433
3434 assertEquals(IMPORTANCE_LOW, r.getImportance());
3435 }
3436
3437 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003438 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3439 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3440 mService.addEnqueuedNotification(r);
3441 NotificationManagerService.WorkerHandler handler = mock(
3442 NotificationManagerService.WorkerHandler.class);
3443 mService.setHandler(handler);
3444 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3445
3446 Bundle signals = new Bundle();
3447 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3448 USER_SENTIMENT_NEGATIVE);
3449 Adjustment adjustment = new Adjustment(
3450 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3451 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3452
3453 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3454
3455 waitForIdle();
3456
3457 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3458 }
3459
3460 @Test
3461 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3462 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3463 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003464 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3465
3466 Bundle signals = new Bundle();
3467 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3468 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003469 Adjustment adjustment = new Adjustment(
3470 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3471 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3472
3473 waitForIdle();
3474
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003475 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003476 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003477
3478 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003479 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3480 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3481 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003482 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003483
3484 Bundle signals = new Bundle();
3485 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003486 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003487 Adjustment adjustment = new Adjustment(
3488 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3489 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3490
3491 waitForIdle();
3492
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003493 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003494 }
3495
3496 @Test
3497 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3498 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3499 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003500 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003501
3502 Bundle signals = new Bundle();
3503 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003504 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003505 Adjustment adjustment = new Adjustment(
3506 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3507 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3508
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003509 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003510 }
3511
3512 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003513 public void testRestore() throws Exception {
3514 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003515 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003516 assertEquals(1, mService.countSystemChecks - systemChecks);
3517 }
3518
3519 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003520 public void testBackupEmptySound() throws Exception {
3521 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3522 channel.setSound(Uri.EMPTY, null);
3523
3524 XmlSerializer serializer = new FastXmlSerializer();
3525 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3526 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3527 channel.writeXmlForBackup(serializer, getContext());
3528
3529 XmlPullParser parser = Xml.newPullParser();
3530 parser.setInput(new BufferedInputStream(
3531 new ByteArrayInputStream(baos.toByteArray())), null);
3532 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3533 restored.populateFromXmlForRestore(parser, getContext());
3534
3535 assertNull(restored.getSound());
3536 }
3537
3538 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003539 public void testBackup() throws Exception {
3540 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04003541 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3542 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003543 mBinderService.getBackupPayload(1);
3544 assertEquals(1, mService.countSystemChecks - systemChecks);
3545 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003546
3547 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003548 public void testEmptyVibration_noException() throws Exception {
3549 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3550 channel.setVibrationPattern(new long[0]);
3551
3552 XmlSerializer serializer = new FastXmlSerializer();
3553 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3554 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3555 channel.writeXml(serializer);
3556 }
3557
3558 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003559 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003560 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003561 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003562 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3563 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003564 message1.setData("",
3565 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003566 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003567 message2.setData("",
3568 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003569
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003570 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003571 .setContentTitle("foo")
3572 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3573 .setStyle(new Notification.MessagingStyle("")
3574 .addMessage(message1)
3575 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003576 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3577 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003578
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003579 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003580 reset(mUgm);
3581 reset(mUgmInternal);
3582 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003583 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003584 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003585 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003586 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003587 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003588 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3589
3590 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003591 .setContentTitle("foo")
3592 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3593 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003594 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3595 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003596
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003597 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003598 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003599 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003600 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003601 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3602 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003603
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003604 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003605 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003606 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003607 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003608 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003609 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003610
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003611 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003612 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003613 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003614 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003615 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003616 anyInt(), anyInt());
3617 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003618
3619 @Test
Robin Leed107af62018-04-27 13:55:56 +02003620 public void testVisitUris() throws Exception {
3621 final Uri audioContents = Uri.parse("content://com.example/audio");
3622 final Uri backgroundImage = Uri.parse("content://com.example/background");
3623
3624 Bundle extras = new Bundle();
3625 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3626 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3627
3628 Notification n = new Notification.Builder(mContext, "a")
3629 .setContentTitle("notification with uris")
3630 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3631 .addExtras(extras)
3632 .build();
3633
3634 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3635 n.visitUris(visitor);
3636 verify(visitor, times(1)).accept(eq(audioContents));
3637 verify(visitor, times(1)).accept(eq(backgroundImage));
3638 }
3639
3640 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003641 public void testSetNotificationPolicy_preP_setOldFields() {
3642 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3643 mService.mZenModeHelper = mZenModeHelper;
3644 NotificationManager.Policy userPolicy =
3645 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3646 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3647
3648 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3649 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3650
3651 int expected = SUPPRESSED_EFFECT_BADGE
3652 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003653 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3654 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003655 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3656
3657 assertEquals(expected, actual);
3658 }
3659
3660 @Test
3661 public void testSetNotificationPolicy_preP_setNewFields() {
3662 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3663 mService.mZenModeHelper = mZenModeHelper;
3664 NotificationManager.Policy userPolicy =
3665 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3666 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3667
3668 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3669 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3670
3671 int expected = SUPPRESSED_EFFECT_BADGE;
3672 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3673
3674 assertEquals(expected, actual);
3675 }
3676
3677 @Test
3678 public void testSetNotificationPolicy_preP_setOldNewFields() {
3679 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3680 mService.mZenModeHelper = mZenModeHelper;
3681 NotificationManager.Policy userPolicy =
3682 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3683 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3684
3685 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3686 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3687
3688 int expected =
3689 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3690 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3691
3692 assertEquals(expected, actual);
3693 }
3694
3695 @Test
3696 public void testSetNotificationPolicy_P_setOldFields() {
3697 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3698 mService.mZenModeHelper = mZenModeHelper;
3699 NotificationManager.Policy userPolicy =
3700 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3701 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3702
3703 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3704 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3705
3706 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3707 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3708 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3709 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3710
3711 assertEquals(expected, actual);
3712 }
3713
3714 @Test
3715 public void testSetNotificationPolicy_P_setNewFields() {
3716 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3717 mService.mZenModeHelper = mZenModeHelper;
3718 NotificationManager.Policy userPolicy =
3719 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3720 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3721
3722 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3723 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3724 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3725
3726 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3727 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3728 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3729 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3730
3731 assertEquals(expected, actual);
3732 }
3733
3734 @Test
3735 public void testSetNotificationPolicy_P_setOldNewFields() {
3736 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3737 mService.mZenModeHelper = mZenModeHelper;
3738 NotificationManager.Policy userPolicy =
3739 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3740 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3741
3742 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3743 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3744
3745 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3746 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3747
3748 assertEquals(expected, actual);
3749
3750 appPolicy = new NotificationManager.Policy(0, 0, 0,
3751 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3752 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3753
3754 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3755 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3756 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3757
3758 assertEquals(expected, actual);
3759 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003760
3761 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003762 public void testVisualDifference_foreground() {
3763 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3764 .setContentTitle("foo");
3765 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3766 nb1.build(), new UserHandle(mUid), null, 0);
3767 NotificationRecord r1 =
3768 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3769
3770 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3771 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3772 .setContentTitle("bar");
3773 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3774 nb2.build(), new UserHandle(mUid), null, 0);
3775 NotificationRecord r2 =
3776 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3777
3778 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3779 }
3780
3781 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003782 public void testVisualDifference_diffTitle() {
3783 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3784 .setContentTitle("foo");
3785 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3786 nb1.build(), new UserHandle(mUid), null, 0);
3787 NotificationRecord r1 =
3788 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3789
3790 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3791 .setContentTitle("bar");
3792 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3793 nb2.build(), new UserHandle(mUid), null, 0);
3794 NotificationRecord r2 =
3795 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3796
3797 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3798 }
3799
3800 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003801 public void testVisualDifference_inboxStyle() {
3802 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3803 .setStyle(new Notification.InboxStyle()
3804 .addLine("line1").addLine("line2"));
3805 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3806 nb1.build(), new UserHandle(mUid), null, 0);
3807 NotificationRecord r1 =
3808 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3809
3810 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3811 .setStyle(new Notification.InboxStyle()
3812 .addLine("line1").addLine("line2_changed"));
3813 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3814 nb2.build(), new UserHandle(mUid), null, 0);
3815 NotificationRecord r2 =
3816 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3817
3818 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3819
3820 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3821 .setStyle(new Notification.InboxStyle()
3822 .addLine("line1"));
3823 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3824 nb3.build(), new UserHandle(mUid), null, 0);
3825 NotificationRecord r3 =
3826 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3827
3828 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3829
3830 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3831 .setStyle(new Notification.InboxStyle()
3832 .addLine("line1").addLine("line2").addLine("line3"));
3833 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3834 nb4.build(), new UserHandle(mUid), null, 0);
3835 NotificationRecord r4 =
3836 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3837
3838 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3839
3840 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3841 .setContentText("not an inbox");
3842 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3843 nb5.build(), new UserHandle(mUid), null, 0);
3844 NotificationRecord r5 =
3845 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3846
3847 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3848 }
3849
3850 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003851 public void testVisualDifference_diffText() {
3852 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3853 .setContentText("foo");
3854 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3855 nb1.build(), new UserHandle(mUid), null, 0);
3856 NotificationRecord r1 =
3857 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3858
3859 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3860 .setContentText("bar");
3861 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3862 nb2.build(), new UserHandle(mUid), null, 0);
3863 NotificationRecord r2 =
3864 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3865
3866 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3867 }
3868
3869 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003870 public void testVisualDifference_sameText() {
3871 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3872 .setContentText("foo");
3873 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3874 nb1.build(), new UserHandle(mUid), null, 0);
3875 NotificationRecord r1 =
3876 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3877
3878 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3879 .setContentText("foo");
3880 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3881 nb2.build(), new UserHandle(mUid), null, 0);
3882 NotificationRecord r2 =
3883 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3884
3885 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3886 }
3887
3888 @Test
3889 public void testVisualDifference_sameTextButStyled() {
3890 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3891 .setContentText(Html.fromHtml("<b>foo</b>"));
3892 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3893 nb1.build(), new UserHandle(mUid), null, 0);
3894 NotificationRecord r1 =
3895 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3896
3897 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3898 .setContentText(Html.fromHtml("<b>foo</b>"));
3899 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3900 nb2.build(), new UserHandle(mUid), null, 0);
3901 NotificationRecord r2 =
3902 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3903
3904 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3905 }
3906
3907 @Test
3908 public void testVisualDifference_diffTextButStyled() {
3909 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3910 .setContentText(Html.fromHtml("<b>foo</b>"));
3911 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3912 nb1.build(), new UserHandle(mUid), null, 0);
3913 NotificationRecord r1 =
3914 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3915
3916 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3917 .setContentText(Html.fromHtml("<b>bar</b>"));
3918 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3919 nb2.build(), new UserHandle(mUid), null, 0);
3920 NotificationRecord r2 =
3921 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3922
3923 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3924 }
3925
3926 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003927 public void testVisualDifference_diffProgress() {
3928 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3929 .setProgress(100, 90, false);
3930 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3931 nb1.build(), new UserHandle(mUid), null, 0);
3932 NotificationRecord r1 =
3933 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3934
3935 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3936 .setProgress(100, 100, false);
3937 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3938 nb2.build(), new UserHandle(mUid), null, 0);
3939 NotificationRecord r2 =
3940 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3941
3942 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3943 }
3944
3945 @Test
3946 public void testVisualDifference_diffProgressNotDone() {
3947 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3948 .setProgress(100, 90, false);
3949 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3950 nb1.build(), new UserHandle(mUid), null, 0);
3951 NotificationRecord r1 =
3952 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3953
3954 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3955 .setProgress(100, 91, false);
3956 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3957 nb2.build(), new UserHandle(mUid), null, 0);
3958 NotificationRecord r2 =
3959 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3960
3961 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3962 }
Beverly5a20a5e2018-03-06 15:02:44 -05003963
3964 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003965 public void testVisualDifference_sameProgressStillDone() {
3966 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3967 .setProgress(100, 100, false);
3968 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3969 nb1.build(), new UserHandle(mUid), null, 0);
3970 NotificationRecord r1 =
3971 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3972
3973 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3974 .setProgress(100, 100, false);
3975 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3976 nb2.build(), new UserHandle(mUid), null, 0);
3977 NotificationRecord r2 =
3978 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3979
3980 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3981 }
3982
3983 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003984 public void testVisualDifference_summary() {
3985 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3986 .setGroup("bananas")
3987 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3988 .setContentText("foo");
3989 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3990 nb1.build(), new UserHandle(mUid), null, 0);
3991 NotificationRecord r1 =
3992 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3993
3994 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3995 .setGroup("bananas")
3996 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3997 .setContentText("bar");
3998 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3999 nb2.build(), new UserHandle(mUid), null, 0);
4000 NotificationRecord r2 =
4001 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4002
4003 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4004 }
4005
4006 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04004007 public void testVisualDifference_summaryNewNotification() {
4008 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4009 .setGroup("bananas")
4010 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4011 .setContentText("bar");
4012 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4013 nb2.build(), new UserHandle(mUid), null, 0);
4014 NotificationRecord r2 =
4015 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4016
4017 assertFalse(mService.isVisuallyInterruptive(null, r2));
4018 }
4019
4020 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05004021 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
4022 // post 2 notification from this package
4023 final NotificationRecord notif1 = generateNotificationRecord(
4024 mTestNotificationChannel, 1, null, true);
4025 final NotificationRecord notif2 = generateNotificationRecord(
4026 mTestNotificationChannel, 2, null, false);
4027 mService.addNotification(notif1);
4028 mService.addNotification(notif2);
4029
4030 // on broadcast, hide the 2 notifications
4031 mService.simulatePackageSuspendBroadcast(true, PKG);
4032 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
4033 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4034 assertEquals(2, captorHide.getValue().size());
4035
4036 // on broadcast, unhide the 2 notifications
4037 mService.simulatePackageSuspendBroadcast(false, PKG);
4038 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
4039 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4040 assertEquals(2, captorUnhide.getValue().size());
4041 }
4042
4043 @Test
4044 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
4045 // post 2 notification from this package
4046 final NotificationRecord notif1 = generateNotificationRecord(
4047 mTestNotificationChannel, 1, null, true);
4048 final NotificationRecord notif2 = generateNotificationRecord(
4049 mTestNotificationChannel, 2, null, false);
4050 mService.addNotification(notif1);
4051 mService.addNotification(notif2);
4052
4053 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4054 mService.simulatePackageSuspendBroadcast(true, "test_package");
4055 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4056 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4057 assertEquals(0, captor.getValue().size());
4058 }
Kristian Monsen05f34792018-04-09 10:27:16 +02004059
4060 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004061 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
4062 // Post 2 notifications from 2 packages
4063 NotificationRecord pkgA = new NotificationRecord(mContext,
4064 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4065 mService.addNotification(pkgA);
4066 NotificationRecord pkgB = new NotificationRecord(mContext,
4067 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4068 mService.addNotification(pkgB);
4069
4070 // on broadcast, hide one of the packages
4071 mService.simulatePackageDistractionBroadcast(
4072 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
4073 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4074 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4075 assertEquals(1, captorHide.getValue().size());
4076 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
4077
4078 // on broadcast, unhide the package
4079 mService.simulatePackageDistractionBroadcast(
4080 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
4081 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4082 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4083 assertEquals(1, captorUnhide.getValue().size());
4084 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
4085 }
4086
4087 @Test
4088 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
4089 // Post 2 notifications from 2 packages
4090 NotificationRecord pkgA = new NotificationRecord(mContext,
4091 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4092 mService.addNotification(pkgA);
4093 NotificationRecord pkgB = new NotificationRecord(mContext,
4094 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4095 mService.addNotification(pkgB);
4096
4097 // on broadcast, hide one of the packages
4098 mService.simulatePackageDistractionBroadcast(
4099 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
4100 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004101
4102 // should be called only once.
4103 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004104 assertEquals(2, captorHide.getValue().size());
4105 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
4106 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
4107
4108 // on broadcast, unhide the package
4109 mService.simulatePackageDistractionBroadcast(
4110 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
4111 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004112
4113 // should be called only once.
4114 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004115 assertEquals(2, captorUnhide.getValue().size());
4116 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
4117 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
4118 }
4119
4120 @Test
4121 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
4122 // post notification from this package
4123 final NotificationRecord notif1 = generateNotificationRecord(
4124 mTestNotificationChannel, 1, null, true);
4125 mService.addNotification(notif1);
4126
4127 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4128 mService.simulatePackageDistractionBroadcast(
4129 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
4130 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4131 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4132 assertEquals(0, captor.getValue().size());
4133 }
4134
4135 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02004136 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
4137 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
4138 when(mActivityManager.isLowRamDevice()).thenReturn(true);
4139 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4140 .thenReturn(new String[] {"a", "b", "c"});
4141 when(mContext.getResources()).thenReturn(mResources);
4142
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004143 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004144 }
4145
4146 @Test
4147 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
4148 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
4149 when(mActivityManager.isLowRamDevice()).thenReturn(true);
4150 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4151 .thenReturn(new String[] {"a", "b", "c"});
4152 when(mContext.getResources()).thenReturn(mResources);
4153
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004154 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004155 }
4156
4157 @Test
4158 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
4159 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
4160 when(mActivityManager.isLowRamDevice()).thenReturn(true);
4161 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4162 .thenReturn(new String[] {"a", "b", "c"});
4163 when(mContext.getResources()).thenReturn(mResources);
4164
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004165 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004166 }
4167
4168 @Test
4169 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
4170 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4171 when(mActivityManager.isLowRamDevice()).thenReturn(true);
4172 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4173 .thenReturn(new String[] {"a", "b", "c"});
4174 when(mContext.getResources()).thenReturn(mResources);
4175
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004176 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004177 }
4178
4179 @Test
4180 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
4181 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
4182 when(mActivityManager.isLowRamDevice()).thenReturn(false);
4183 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4184 .thenReturn(new String[] {"a", "b", "c"});
4185 when(mContext.getResources()).thenReturn(mResources);
4186
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004187 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004188 }
4189
4190 @Test
4191 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
4192 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4193 when(mActivityManager.isLowRamDevice()).thenReturn(false);
4194 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4195 .thenReturn(new String[] {"a", "b", "c"});
4196 when(mContext.getResources()).thenReturn(mResources);
4197
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004198 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4199 }
4200
4201 @Test
4202 public void testCanUseManagedServices_hasPermission() throws Exception {
4203 when(mPackageManager.checkPermission("perm", "pkg", 0))
4204 .thenReturn(PackageManager.PERMISSION_GRANTED);
4205
4206 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4207 }
4208
4209 @Test
4210 public void testCanUseManagedServices_noPermission() throws Exception {
4211 when(mPackageManager.checkPermission("perm", "pkg", 0))
4212 .thenReturn(PackageManager.PERMISSION_DENIED);
4213
4214 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4215 }
4216
4217 @Test
4218 public void testCanUseManagedServices_permDoesNotMatter() {
4219 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004220 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004221
4222 @Test
4223 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4224 final NotificationRecord r = generateNotificationRecord(
4225 mTestNotificationChannel, 1, null, true);
4226 r.setTextChanged(true);
4227 mService.addNotification(r);
4228
4229 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4230 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4231 new NotificationVisibility[]{});
4232
4233 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4234 }
4235
4236 @Test
4237 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4238 throws RemoteException {
4239 final NotificationRecord r = generateNotificationRecord(
4240 mTestNotificationChannel, 1, null, true);
4241 r.setTextChanged(true);
4242 mService.addNotification(r);
4243
4244 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4245
4246 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4247 }
4248
4249 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004250 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004251 throws RemoteException {
4252 final NotificationRecord r = generateNotificationRecord(
4253 mTestNotificationChannel, 1, null, true);
4254 r.setInterruptive(true);
4255 mService.addNotification(r);
4256
4257 mService.maybeRecordInterruptionLocked(r);
4258 mService.maybeRecordInterruptionLocked(r);
4259
4260 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4261 anyString(), anyString(), anyInt());
4262 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004263
4264 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004265 public void testBubble() throws Exception {
4266 mBinderService.setBubblesAllowed(PKG, mUid, false);
4267 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004268 }
4269
4270 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08004271 public void testUserApprovedBubblesForPackage() throws Exception {
4272 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4273 mBinderService.setBubblesAllowed(PKG, mUid, true);
4274 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4275 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
4276 }
4277
4278 @Test
4279 public void testUserRejectsBubblesForPackage() throws Exception {
4280 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4281 mBinderService.setBubblesAllowed(PKG, mUid, false);
4282 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4283 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
4284 }
4285
4286 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004287 public void testIsCallerInstantApp_primaryUser() throws Exception {
4288 ApplicationInfo info = new ApplicationInfo();
4289 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4290 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004291 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004292
Julia Reynolds268647a2018-10-25 16:54:27 -04004293 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004294
4295 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004296 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004297 }
4298
4299 @Test
4300 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4301 ApplicationInfo info = new ApplicationInfo();
4302 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4303 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4304 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004305 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004306
Julia Reynolds268647a2018-10-25 16:54:27 -04004307 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004308 }
4309
4310 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004311 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4312 ApplicationInfo info = new ApplicationInfo();
4313 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004314 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004315 .thenReturn(info);
4316 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4317
4318 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4319
4320 info.privateFlags = 0;
4321 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4322 }
4323
4324 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004325 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4326 ApplicationInfo info = new ApplicationInfo();
4327 info.uid = Binder.getCallingUid();
4328 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4329 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4330
4331 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4332
4333 assertEquals(info.uid, actualUid);
4334 }
4335
4336 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004337 public void testResolveNotificationUid_sameApp() throws Exception {
4338 ApplicationInfo info = new ApplicationInfo();
4339 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004340 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004341
4342 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4343
4344 assertEquals(info.uid, actualUid);
4345 }
4346
4347 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004348 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004349 ApplicationInfo info = new ApplicationInfo();
4350 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004351 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004352
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004353 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4354
4355 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004356 }
4357
4358 @Test
4359 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4360 ApplicationInfo info = new ApplicationInfo();
4361 info.uid = 1356347;
4362 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4363
4364 try {
4365 mService.resolveNotificationUid("caller", "caller", 9, 0);
4366 fail("Incorrect uid didn't throw security exception");
4367 } catch (SecurityException e) {
4368 // yay
4369 }
4370 }
4371
4372 @Test
4373 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4374 int expectedUid = 123;
4375
4376 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4377 mService.setPreferencesHelper(mPreferencesHelper);
4378 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4379 .thenReturn(true);
4380
4381 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4382 }
4383
4384 @Test
4385 public void testResolveNotificationUid_androidAllowed() throws Exception {
4386 int expectedUid = 123;
4387
4388 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4389 // no delegate
4390
4391 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4392 }
4393
4394 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004395 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4396 final String notReal = "NOT REAL";
4397 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4398 PackageManager.NameNotFoundException.class);
4399 ApplicationInfo ai = new ApplicationInfo();
4400 ai.uid = -1;
4401 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4402
4403 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4404 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004405 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4406 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004407 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4408 fail("can't post notifications for nonexistent packages, even if you exist");
4409 } catch (SecurityException e) {
4410 // yay
4411 }
4412 }
4413
4414 @Test
4415 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4416 final String notReal = "NOT REAL";
4417 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4418 PackageManager.NameNotFoundException.class);
4419 ApplicationInfo ai = new ApplicationInfo();
4420 ai.uid = -1;
4421 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4422
4423 // unlike the post case, ignore instead of throwing
4424 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4425
4426 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4427 sbn.getId(), sbn.getUserId());
4428 }
4429
4430 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004431 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4432 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4433 // no delegate
4434
4435 try {
4436 mService.resolveNotificationUid("caller", "target", 9, 0);
4437 fail("Incorrect uid didn't throw security exception");
4438 } catch (SecurityException e) {
4439 // yay
4440 }
4441 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004442
4443 @Test
4444 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4445 Notification n = new Notification.Builder(mContext, "").build();
4446 n.flags |= FLAG_FOREGROUND_SERVICE;
4447
4448 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4449 n, new UserHandle(mUid), null, 0);
4450 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4451
4452 mService.addEnqueuedNotification(r);
4453
4454 mInternalService.removeForegroundServiceFlagFromNotification(
4455 PKG, r.sbn.getId(), r.sbn.getUserId());
4456
4457 waitForIdle();
4458
4459 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4460 }
4461
4462 @Test
4463 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4464 Notification n = new Notification.Builder(mContext, "").build();
4465 n.flags |= FLAG_FOREGROUND_SERVICE;
4466
4467 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4468 n, new UserHandle(mUid), null, 0);
4469 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4470
4471 mService.addNotification(r);
4472
4473 mInternalService.removeForegroundServiceFlagFromNotification(
4474 PKG, r.sbn.getId(), r.sbn.getUserId());
4475
4476 waitForIdle();
4477
4478 ArgumentCaptor<NotificationRecord> captor =
4479 ArgumentCaptor.forClass(NotificationRecord.class);
4480 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4481
4482 assertEquals(0, captor.getValue().getNotification().flags);
4483 }
Beverly58b24532018-10-02 09:08:23 -04004484
4485 @Test
4486 public void testAllowForegroundToasts() throws Exception {
4487 final String testPackage = "testPackageName";
4488 assertEquals(0, mService.mToastQueue.size());
4489 mService.isSystemUid = false;
4490
4491 // package is not suspended
4492 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4493 .thenReturn(false);
4494
4495 // notifications from this package are blocked by the user
4496 mService.setPreferencesHelper(mPreferencesHelper);
4497 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4498
4499 // this app is in the foreground
4500 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4501
4502 // enqueue toast -> toast should still enqueue
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004503 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004504 new TestableToastCallback(), 2000, 0);
4505 assertEquals(1, mService.mToastQueue.size());
4506 }
4507
4508 @Test
4509 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4510 final String testPackage = "testPackageName";
4511 assertEquals(0, mService.mToastQueue.size());
4512 mService.isSystemUid = false;
4513
4514 // package is suspended
4515 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4516 .thenReturn(true);
4517
4518 // notifications from this package are NOT blocked by the user
4519 mService.setPreferencesHelper(mPreferencesHelper);
4520 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4521
4522 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004523 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004524 new TestableToastCallback(), 2000, 0);
4525 assertEquals(0, mService.mToastQueue.size());
4526 }
4527
4528 @Test
4529 public void testDisallowToastsFromBlockedApps() throws Exception {
4530 final String testPackage = "testPackageName";
4531 assertEquals(0, mService.mToastQueue.size());
4532 mService.isSystemUid = false;
4533
4534 // package is not suspended
4535 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4536 .thenReturn(false);
4537
4538 // notifications from this package are blocked by the user
4539 mService.setPreferencesHelper(mPreferencesHelper);
4540 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4541
4542 // this app is NOT in the foreground
4543 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4544
4545 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004546 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004547 new TestableToastCallback(), 2000, 0);
4548 assertEquals(0, mService.mToastQueue.size());
4549 }
4550
4551 @Test
4552 public void testAlwaysAllowSystemToasts() throws Exception {
4553 final String testPackage = "testPackageName";
4554 assertEquals(0, mService.mToastQueue.size());
4555 mService.isSystemUid = true;
4556
4557 // package is suspended
4558 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4559 .thenReturn(true);
4560
4561 // notifications from this package ARE blocked by the user
4562 mService.setPreferencesHelper(mPreferencesHelper);
4563 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4564
4565 // this app is NOT in the foreground
4566 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4567
4568 // enqueue toast -> system toast can still be enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004569 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004570 new TestableToastCallback(), 2000, 0);
4571 assertEquals(1, mService.mToastQueue.size());
4572 }
Tony Mak29996702018-11-26 16:23:34 +00004573
4574 @Test
Alex Mang509e5542020-01-03 13:06:40 -08004575 public void testOnPanelRevealedAndHidden() {
4576 int items = 5;
4577 mService.mNotificationDelegate.onPanelRevealed(false, items);
4578 verify(mAssistants, times(1)).onPanelRevealed(eq(items));
4579
4580 mService.mNotificationDelegate.onPanelHidden();
4581 verify(mAssistants, times(1)).onPanelHidden();
4582 }
4583
4584 @Test
Tony Mak29996702018-11-26 16:23:34 +00004585 public void testOnNotificationSmartReplySent() {
4586 final int replyIndex = 2;
4587 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004588 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004589 final boolean generatedByAssistant = true;
4590
4591 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004592 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004593 mService.addNotification(r);
4594
4595 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004596 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4597 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004598 verify(mAssistants).notifyAssistantSuggestedReplySent(
4599 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4600 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004601
4602 @Test
4603 public void testOnNotificationActionClick() {
4604 final int actionIndex = 2;
4605 final Notification.Action action =
4606 new Notification.Action.Builder(null, "text", null).build();
4607 final boolean generatedByAssistant = false;
4608
4609 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4610 mService.addNotification(r);
4611
4612 NotificationVisibility notificationVisibility =
4613 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4614 mService.mNotificationDelegate.onNotificationActionClick(
4615 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4616 generatedByAssistant);
4617 verify(mAssistants).notifyAssistantActionClicked(
4618 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4619 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004620
4621 @Test
4622 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4623 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4624 mService.addNotification(r);
4625
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004626 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4627 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004628 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4629 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4630 };
4631 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4632 new NotificationVisibility[0]);
4633
4634 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4635 }
4636
4637 @Test
4638 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4639 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4640 mService.addNotification(r);
4641
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004642 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4643 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004644
4645 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4646 }
4647
4648 @Test
4649 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4650 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4651 mService.addNotification(r);
4652
Julia Reynolds95334132018-12-19 11:15:35 -05004653 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004654 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4655 };
4656 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4657 new NotificationVisibility[0]);
4658
4659 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4660 }
Julia Reynolds95334132018-12-19 11:15:35 -05004661
Colin Cross5ea7fb72019-12-18 17:16:36 -08004662 @Test
Julia Reynolds95334132018-12-19 11:15:35 -05004663 public void testReportSeen_delegated() {
4664 Notification.Builder nb =
4665 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4666 .setContentTitle("foo")
4667 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4668
4669 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4670 nb.build(), new UserHandle(mUid), null, 0);
4671 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4672
4673 mService.reportSeen(r);
4674 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4675
4676 }
4677
4678 @Test
4679 public void testReportSeen_notDelegated() {
4680 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4681
4682 mService.reportSeen(r);
4683 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4684 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004685
4686 @Test
4687 public void testNotificationStats_notificationError() {
4688 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4689 mService.addNotification(r);
4690
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004691 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.sbn.getId(),
4692 r.sbn.getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004693 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4694 new UserHandle(mUid), null, 0);
4695 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4696 mService.addEnqueuedNotification(update);
4697 assertNull(update.sbn.getNotification().getSmallIcon());
4698
4699 NotificationManagerService.PostNotificationRunnable runnable =
4700 mService.new PostNotificationRunnable(update.getKey());
4701 runnable.run();
4702 waitForIdle();
4703
4704 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4705 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4706 assertNotNull(captor.getValue());
4707 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004708
4709 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004710 public void testCanNotifyAsUser_crossUser() throws Exception {
4711 // same user no problem
4712 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4713
4714 // cross user, no permission, problem
4715 try {
4716 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4717 fail("Should not be callable cross user without cross user permission");
4718 } catch (SecurityException e) {
4719 // good
4720 }
4721
4722 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05004723 enableInteractAcrossUsers();
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004724 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4725 }
4726
4727 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004728 public void testgetNotificationChannels_crossUser() throws Exception {
4729 // same user no problem
4730 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4731
4732 // cross user, no permission, problem
4733 try {
4734 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4735 fail("Should not be callable cross user without cross user permission");
4736 } catch (SecurityException e) {
4737 // good
4738 }
4739
4740 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05004741 enableInteractAcrossUsers();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004742 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4743 }
4744
4745 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004746 public void setDefaultAssistantForUser_fromConfigXml() {
4747 clearDeviceConfig();
4748 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04004749 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004750 when(mResources
4751 .getString(
4752 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4753 .thenReturn(xmlConfig.flattenToString());
4754 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04004755 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
4756 .thenReturn(components);
4757 when(mAssistants.getDefaultComponents())
4758 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00004759 mService.setNotificationAssistantAccessGrantedCallback(
4760 mNotificationAssistantAccessGrantedCallback);
4761
Jay Aliomer4204f252019-08-26 11:36:53 -04004762
Tony Mak9a3c1f12019-03-04 16:04:42 +00004763 mService.setDefaultAssistantForUser(0);
4764
4765 verify(mNotificationAssistantAccessGrantedCallback)
4766 .onGranted(eq(xmlConfig), eq(0), eq(true));
4767 }
4768
4769 @Test
4770 public void setDefaultAssistantForUser_fromDeviceConfig() {
4771 ComponentName xmlConfig = new ComponentName("xml", "config");
4772 ComponentName deviceConfig = new ComponentName("device", "config");
4773 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4774 when(mResources
4775 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4776 .thenReturn(xmlConfig.flattenToString());
4777 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04004778 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00004779 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04004780 when(mAssistants.getDefaultComponents())
4781 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004782 mService.setNotificationAssistantAccessGrantedCallback(
4783 mNotificationAssistantAccessGrantedCallback);
4784
4785 mService.setDefaultAssistantForUser(0);
4786
4787 verify(mNotificationAssistantAccessGrantedCallback)
4788 .onGranted(eq(deviceConfig), eq(0), eq(true));
4789 }
4790
4791 @Test
4792 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4793 ComponentName xmlConfig = new ComponentName("xml", "config");
4794 ComponentName deviceConfig = new ComponentName("device", "config");
4795 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4796 when(mResources
4797 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4798 .thenReturn(xmlConfig.flattenToString());
4799 when(mContext.getResources()).thenReturn(mResources);
4800 // Only xmlConfig is valid, deviceConfig is not.
4801 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04004802 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
4803 when(mAssistants.getDefaultComponents())
4804 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004805 mService.setNotificationAssistantAccessGrantedCallback(
4806 mNotificationAssistantAccessGrantedCallback);
4807
4808 mService.setDefaultAssistantForUser(0);
4809
4810 verify(mNotificationAssistantAccessGrantedCallback)
4811 .onGranted(eq(xmlConfig), eq(0), eq(true));
4812 }
4813
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004814 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04004815 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
4816 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
4817 generateResetComponentValues();
4818 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
4819 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
4820 ComponentName deviceConfig1 = new ComponentName("device", "config1");
4821 ComponentName deviceConfig2 = new ComponentName("device", "config2");
4822 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
4823 changes.put(false, new ArrayList());
4824 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
4825 mService.getBinderService().clearData("device", 0, false);
4826 verify(mAssistants, times(1))
4827 .setPackageOrComponentEnabled(
4828 eq("device/config2"),
4829 eq(0), eq(true), eq(false));
4830 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4831 eq("device"), eq(0), eq(false), eq(true));
4832 }
4833
4834 @Test
4835 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
4836 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
4837 generateResetComponentValues();
4838 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
4839 ComponentName deviceConfig = new ComponentName("device", "config");
4840 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
4841 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
4842 changes.put(false, new ArrayList());
4843 when(mListeners.resetComponents(anyString(), anyInt()))
4844 .thenReturn(changes);
4845 mService.getBinderService().clearData("device", 0, false);
4846 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4847 eq("device"), eq(0), eq(false), eq(true));
4848 }
4849
4850 @Test
4851 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
4852 ComponentName deviceConfig = new ComponentName("device", "config");
4853 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
4854 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
4855 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
4856 mService.getBinderService().clearData("device", 0, false);
4857 verify(mConditionProviders, times(1)).resetPackage(
4858 eq("device"), eq(0));
4859 }
4860
4861 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004862 public void testFlagBubble() throws RemoteException {
4863 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05004864 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004865
Mady Mellor9e923e12019-12-17 16:08:46 -08004866 NotificationRecord nr =
4867 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
Mady Mellor65dcaa92019-04-03 12:21:44 -07004868
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004869 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor65dcaa92019-04-03 12:21:44 -07004870 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4871 waitForIdle();
4872
4873 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4874 assertEquals(1, notifs.length);
4875 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4876 assertTrue(mService.getNotificationRecord(
4877 nr.sbn.getKey()).getNotification().isBubbleNotification());
4878 }
4879
4880 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004881 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4882 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05004883 setUpPrefsForBubbles(PKG, mUid, true /* global */, false /* app */, true /* channel */);
Mady Mellorc6820342019-05-20 12:04:36 -07004884
Mady Mellor9e923e12019-12-17 16:08:46 -08004885 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
4886 "testFlagBubble_noFlag_appNotAllowed");
Mady Mellorc6820342019-05-20 12:04:36 -07004887
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004888 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorc6820342019-05-20 12:04:36 -07004889 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4890 waitForIdle();
4891
4892 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4893 assertEquals(1, notifs.length);
4894 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4895 assertFalse(mService.getNotificationRecord(
4896 nr.sbn.getKey()).getNotification().isBubbleNotification());
4897 }
4898
4899 @Test
Mady Mellor9e923e12019-12-17 16:08:46 -08004900 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004901 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05004902 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004903
Mady Mellorbe797962019-04-01 16:04:24 -07004904 // Notif with bubble metadata but not our other misc requirements
Mady Mellor9e923e12019-12-17 16:08:46 -08004905 Notification.Builder nb = new Notification.Builder(mContext,
4906 mTestNotificationChannel.getId())
4907 .setContentTitle("foo")
4908 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4909 .setBubbleMetadata(getBubbleMetadataBuilder().build());
4910 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
4911 nb.build(), new UserHandle(mUid), null, 0);
4912 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellorbe797962019-04-01 16:04:24 -07004913
4914 // Say we're foreground
4915 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4916 IMPORTANCE_FOREGROUND);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004917 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004918 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4919 waitForIdle();
4920
Mady Mellor9e923e12019-12-17 16:08:46 -08004921 // if notif isn't configured properly it doesn't get to bubble just because app is
4922 // foreground.
Mady Mellorbe797962019-04-01 16:04:24 -07004923 assertFalse(mService.getNotificationRecord(
4924 nr.sbn.getKey()).getNotification().isBubbleNotification());
4925 }
4926
4927 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004928 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4929 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05004930 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004931
Mady Mellor9e923e12019-12-17 16:08:46 -08004932 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
4933 "testFlagBubbleNotifs_flag_messaging");
Mady Mellorbe797962019-04-01 16:04:24 -07004934
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004935 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004936 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4937 waitForIdle();
4938
4939 // yes allowed, yes messaging, yes bubble
4940 assertTrue(mService.getNotificationRecord(
Mady Mellor9e923e12019-12-17 16:08:46 -08004941 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07004942 }
4943
4944 @Test
4945 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4946 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05004947 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004948
4949 // Give it bubble metadata
Mady Mellor9e923e12019-12-17 16:08:46 -08004950 Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004951 // Give it a person
4952 Person person = new Person.Builder()
4953 .setName("bubblebot")
4954 .build();
4955 // Make it a phone call
4956 Notification.Builder nb = new Notification.Builder(mContext,
4957 mTestNotificationChannel.getId())
4958 .setCategory(CATEGORY_CALL)
4959 .addPerson(person)
4960 .setContentTitle("foo")
4961 .setBubbleMetadata(data)
4962 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4963
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004964 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4965 "testFlagBubbleNotifs_flag_phonecall", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07004966 nb.build(), new UserHandle(mUid), null, 0);
4967 // Make sure it has foreground service
4968 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4969 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4970
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004971 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004972 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4973 waitForIdle();
4974
4975 // yes phone call, yes person, yes foreground service, yes bubble
4976 assertTrue(mService.getNotificationRecord(
4977 sbn.getKey()).getNotification().isBubbleNotification());
4978 }
4979
4980 @Test
4981 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4982 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05004983 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004984
4985 // Give it bubble metadata
Mady Mellor9e923e12019-12-17 16:08:46 -08004986 Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004987 // Give it a person
4988 Person person = new Person.Builder()
4989 .setName("bubblebot")
4990 .build();
4991 // Make it a phone call
4992 Notification.Builder nb = new Notification.Builder(mContext,
4993 mTestNotificationChannel.getId())
4994 .setCategory(CATEGORY_CALL)
4995 .addPerson(person)
4996 .setContentTitle("foo")
4997 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004998 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4999
5000 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5001 nb.build(), new UserHandle(mUid), null, 0);
5002 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5003
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005004 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005005 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5006 waitForIdle();
5007
Mady Mellorbe797962019-04-01 16:04:24 -07005008 // yes phone call, yes person, NO foreground service, no bubble
5009 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005010 sbn.getKey()).getNotification().isBubbleNotification());
5011 }
5012
5013 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005014 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
5015 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005016 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005017
5018 // Give it bubble metadata
Mady Mellor9e923e12019-12-17 16:08:46 -08005019 Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005020 // Make it a phone call
5021 Notification.Builder nb = new Notification.Builder(mContext,
5022 mTestNotificationChannel.getId())
5023 .setCategory(CATEGORY_CALL)
5024 .setContentTitle("foo")
5025 .setBubbleMetadata(data)
5026 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5027
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005028 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5029 "testFlagBubbleNotifs_noFlag_phonecall_noPerson", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005030 nb.build(), new UserHandle(mUid), null, 0);
5031 // Make sure it has foreground service
5032 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5033 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5034
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005035 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005036 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5037 waitForIdle();
5038
5039 // yes phone call, yes foreground service, BUT NO person, no bubble
5040 assertFalse(mService.getNotificationRecord(
5041 sbn.getKey()).getNotification().isBubbleNotification());
5042 }
5043
5044 @Test
5045 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
5046 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005047 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005048
5049 // Give it bubble metadata
Mady Mellor9e923e12019-12-17 16:08:46 -08005050 Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005051 // Give it a person
5052 Person person = new Person.Builder()
5053 .setName("bubblebot")
5054 .build();
5055 // No category
5056 Notification.Builder nb = new Notification.Builder(mContext,
5057 mTestNotificationChannel.getId())
5058 .addPerson(person)
5059 .setContentTitle("foo")
5060 .setBubbleMetadata(data)
5061 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5062
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005063 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5064 "testFlagBubbleNotifs_noFlag_phonecall_noCategory", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005065 nb.build(), new UserHandle(mUid), null, 0);
5066 // Make sure it has foreground service
5067 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5068 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5069
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005070 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005071 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5072 waitForIdle();
5073
5074 // yes person, yes foreground service, BUT NO call, no bubble
5075 assertFalse(mService.getNotificationRecord(
5076 sbn.getKey()).getNotification().isBubbleNotification());
5077 }
5078
5079 @Test
5080 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005081 // Bubbles are NOT allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005082 setUpPrefsForBubbles(PKG, mUid, true /* global */, false /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005083
Mady Mellor9e923e12019-12-17 16:08:46 -08005084 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5085 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005086
5087 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005088 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005089 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5090 waitForIdle();
5091
5092 // not allowed, no bubble
5093 assertFalse(mService.getNotificationRecord(
Mady Mellor9e923e12019-12-17 16:08:46 -08005094 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005095 }
5096
5097 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005098 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005099 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005100 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005101
Mady Mellor9e923e12019-12-17 16:08:46 -08005102 // Messaging notif WITHOUT bubble metadata
5103 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
5104 null /* groupKey */, false /* isSummary */);
5105
5106 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5107 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
5108 nb.build(), new UserHandle(mUid), null, 0);
5109 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005110
5111 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005112 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005113 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5114 waitForIdle();
5115
5116 // no bubble metadata, no bubble
5117 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07005118 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005119 }
5120
5121 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005122 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005123 // Bubbles are allowed except on this channel
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005124 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005125
Mady Mellor9e923e12019-12-17 16:08:46 -08005126 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5127 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005128
5129 // Post the notification
Mady Mellor9e923e12019-12-17 16:08:46 -08005130 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005131 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5132 waitForIdle();
5133
5134 // channel not allowed, no bubble
5135 assertFalse(mService.getNotificationRecord(
Mady Mellor9e923e12019-12-17 16:08:46 -08005136 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005137 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005138
Mady Mellor49b1bf12019-03-29 12:00:02 -07005139 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005140 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005141 // Bubbles are not allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005142 setUpPrefsForBubbles(PKG, mUid, false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005143
5144 // Give it bubble metadata
Mady Mellor9e923e12019-12-17 16:08:46 -08005145 Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005146 // Give it a person
5147 Person person = new Person.Builder()
5148 .setName("bubblebot")
5149 .build();
5150 // Make it a phone call
5151 Notification.Builder nb = new Notification.Builder(mContext,
5152 mTestNotificationChannel.getId())
5153 .setCategory(CATEGORY_CALL)
5154 .addPerson(person)
5155 .setContentTitle("foo")
5156 .setBubbleMetadata(data)
5157 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5158
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005159 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5160 "testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005161 nb.build(), new UserHandle(mUid), null, 0);
5162 // Make sure it has foreground service
5163 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Mady Mellorbe797962019-04-01 16:04:24 -07005164
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005165 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds0f767342019-12-18 09:11:55 -05005166 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005167 waitForIdle();
5168
5169 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
5170 assertFalse(mService.getNotificationRecord(
5171 sbn.getKey()).getNotification().isBubbleNotification());
5172 }
5173
5174 @Test
5175 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005176 // Bubbles are allowed, but not on channel.
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005177 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005178
5179 // Give it bubble metadata
Mady Mellor9e923e12019-12-17 16:08:46 -08005180 Notification.BubbleMetadata data = getBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005181 // Give it a person
5182 Person person = new Person.Builder()
5183 .setName("bubblebot")
5184 .build();
5185 // Make it a phone call
5186 Notification.Builder nb = new Notification.Builder(mContext,
5187 mTestNotificationChannel.getId())
5188 .setCategory(CATEGORY_CALL)
5189 .addPerson(person)
5190 .setContentTitle("foo")
5191 .setBubbleMetadata(data)
5192 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5193
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005194 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5195 "testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005196 nb.build(), new UserHandle(mUid), null, 0);
5197 // Make sure it has foreground service
5198 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5199 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5200
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005201 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005202 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5203 waitForIdle();
5204
5205 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
5206 assertFalse(mService.getNotificationRecord(
5207 sbn.getKey()).getNotification().isBubbleNotification());
5208 }
5209
5210 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005211 public void testCancelAllNotifications_cancelsBubble() throws Exception {
5212 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5213 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
5214 mService.addNotification(nr);
5215
5216 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
5217 waitForIdle();
5218
5219 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5220 assertEquals(0, notifs.length);
5221 assertEquals(0, mService.getNotificationRecordCount());
5222 }
5223
5224 @Test
5225 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
5226 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5227 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5228
5229 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005230 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5231 "testAppCancelNotifications_cancelsBubbles",
Mady Mellor49b1bf12019-03-29 12:00:02 -07005232 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
5233 waitForIdle();
5234
5235 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5236 assertEquals(1, notifs.length);
5237 assertEquals(1, mService.getNotificationRecordCount());
5238
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005239 mBinderService.cancelNotificationWithTag(PKG, PKG,
5240 "testAppCancelNotifications_cancelsBubbles", nrBubble.sbn.getId(),
Mady Mellor49b1bf12019-03-29 12:00:02 -07005241 nrBubble.sbn.getUserId());
5242 waitForIdle();
5243
5244 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5245 assertEquals(0, notifs2.length);
5246 assertEquals(0, mService.getNotificationRecordCount());
5247 }
5248
5249 @Test
5250 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5251 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5252 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5253 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5254
5255 mService.addNotification(nrNormal);
5256 mService.addNotification(nrBubble);
5257
5258 mService.getBinderService().cancelNotificationsFromListener(null, null);
5259 waitForIdle();
5260
5261 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5262 assertEquals(1, notifs.length);
5263 assertEquals(1, mService.getNotificationRecordCount());
5264 }
5265
5266 @Test
5267 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
5268 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5269 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5270 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5271
5272 mService.addNotification(nrNormal);
5273 mService.addNotification(nrBubble);
5274
5275 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
5276 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5277 waitForIdle();
5278
5279 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5280 assertEquals(1, notifs.length);
5281 assertEquals(1, mService.getNotificationRecordCount());
5282 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005283
Julia Reynolds4214da92019-04-10 15:04:06 -04005284 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005285 public void testGetAllowedAssistantAdjustments() throws Exception {
5286 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005287 assertNotNull(capabilities);
5288
5289 for (int i = capabilities.size() - 1; i >= 0; i--) {
5290 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005291 mBinderService.disallowAssistantAdjustment(capability);
5292 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5293 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005294 assertNotNull(currentCapabilities);
5295 assertFalse(currentCapabilities.contains(capability));
5296 }
5297 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005298
Julia Reynolds4214da92019-04-10 15:04:06 -04005299 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005300 public void testAdjustRestrictedKey() throws Exception {
5301 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005302 mService.addNotification(r);
5303 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005304
5305 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5306 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5307
5308 Bundle signals = new Bundle();
5309 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5310 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
5311 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
5312 "", r.getUser().getIdentifier());
5313
5314 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5315 r.applyAdjustments();
5316
5317 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5318 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5319 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005320
Julia Reynolds4214da92019-04-10 15:04:06 -04005321 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005322 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005323 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5324 .thenReturn(true);
5325 mService.setZenHelper(mock(ZenModeHelper.class));
5326 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005327 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5328 boolean isEnabled = true;
5329 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5330 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5331
5332 try {
5333 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005334 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005335 } catch (IllegalArgumentException e) {
5336 // yay
5337 }
5338
5339 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5340 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5341 mBinderService.addAutomaticZenRule(rule);
5342
5343 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5344 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5345 mBinderService.addAutomaticZenRule(rule);
5346 }
5347
Julia Reynolds4214da92019-04-10 15:04:06 -04005348 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005349 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5350 try {
5351 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5352 mUid + UserHandle.PER_USER_RANGE);
5353 fail("Cannot call cross user without permission");
5354 } catch (SecurityException e) {
5355 // pass
5356 }
5357
5358 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005359 enableInteractAcrossUsers();
Julia Reynolds657d1642019-03-27 12:15:57 -04005360 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5361 mUid + UserHandle.PER_USER_RANGE);
5362 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005363
Julia Reynolds4214da92019-04-10 15:04:06 -04005364 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005365 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5366 try {
5367 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5368 mUid + UserHandle.PER_USER_RANGE);
5369 fail("Cannot call cross user without permission");
5370 } catch (SecurityException e) {
5371 // pass
5372 }
5373
5374 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005375 enableInteractAcrossUsers();
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005376 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5377 mUid + UserHandle.PER_USER_RANGE);
5378 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005379
Will Brockmancfd98302020-01-29 15:57:30 -05005380 private void enableInteractAcrossUsers() {
5381 TestablePermissions perms = mContext.getTestablePermissions();
5382 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5383 }
5384
Mady Mellora54e9fa2019-04-18 13:26:18 -07005385 @Test
5386 public void testNotificationBubbleChanged_false() throws Exception {
5387 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005388 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005389
Mady Mellor9e923e12019-12-17 16:08:46 -08005390 // Notif with bubble metadata
5391 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5392 "testNotificationBubbleChanged_false");
Mady Mellora54e9fa2019-04-18 13:26:18 -07005393
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005394 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005395 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5396 waitForIdle();
5397
Mady Mellor66efd5e2019-05-15 13:38:11 -07005398 // Reset as this is called when the notif is first sent
5399 reset(mListeners);
5400
Mady Mellora54e9fa2019-04-18 13:26:18 -07005401 // First we were a bubble
5402 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5403 assertEquals(1, notifsBefore.length);
5404 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5405
5406 // Notify we're not a bubble
5407 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5408 waitForIdle();
5409
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005410 // Make sure we are not a bubble
5411 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5412 assertEquals(1, notifsAfter.length);
5413 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005414 }
5415
5416 @Test
5417 public void testNotificationBubbleChanged_true() throws Exception {
5418 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005419 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005420
Mady Mellor9e923e12019-12-17 16:08:46 -08005421 // Notif that is not a bubble
Mady Mellora54e9fa2019-04-18 13:26:18 -07005422 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08005423 1, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005424 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005425 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5426 waitForIdle();
5427
5428 // Would be a normal notification because wouldn't have met requirements to bubble
5429 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5430 assertEquals(1, notifsBefore.length);
5431 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5432
Mady Mellor9e923e12019-12-17 16:08:46 -08005433 // Update the notification to be message style / meet bubble requirements
5434 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5435 nr.sbn.getTag());
5436 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(),
5437 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
5438 waitForIdle();
Mady Mellora54e9fa2019-04-18 13:26:18 -07005439
Mady Mellor66efd5e2019-05-15 13:38:11 -07005440 // Reset as this is called when the notif is first sent
5441 reset(mListeners);
5442
Mady Mellora54e9fa2019-04-18 13:26:18 -07005443 // Notify we are now a bubble
5444 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5445 waitForIdle();
5446
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005447 // Make sure we are a bubble
5448 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5449 assertEquals(1, notifsAfter.length);
5450 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005451 }
5452
5453 @Test
5454 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5455 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005456 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005457
5458 // Notif that is not a bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005459 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005460 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005461 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5462 waitForIdle();
5463
Mady Mellor66efd5e2019-05-15 13:38:11 -07005464 // Reset as this is called when the notif is first sent
5465 reset(mListeners);
5466
Mady Mellora54e9fa2019-04-18 13:26:18 -07005467 // Would be a normal notification because wouldn't have met requirements to bubble
5468 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5469 assertEquals(1, notifsBefore.length);
5470 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5471
5472 // Notify we are now a bubble
5473 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5474 waitForIdle();
5475
5476 // We still wouldn't be a bubble because the notification didn't meet requirements
5477 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5478 assertEquals(1, notifsAfter.length);
5479 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5480 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005481
5482 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -08005483 public void testOnBubbleNotificationSuppressionChanged() throws Exception {
5484 // Bubble notification
5485 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5486
5487 // Bubbles are allowed!
5488 setUpPrefsForBubbles(PKG, nr.sbn.getUserId(), true /* global */,
5489 true /* app */, true /* channel */);
5490
5491 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
5492 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5493 waitForIdle();
5494
5495 // NOT suppressed
5496 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5497 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5498
5499 // Reset as this is called when the notif is first sent
5500 reset(mListeners);
5501
5502 // Test: update suppression to true
5503 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
5504 waitForIdle();
5505
5506 // Check
5507 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5508 assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
5509
5510 // Reset to check again
5511 reset(mListeners);
5512
5513 // Test: update suppression to false
5514 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
5515 waitForIdle();
5516
5517 // Check
5518 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5519 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5520 }
5521
5522 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005523 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
5524 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5525 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5526 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5527 waitForIdle();
5528
5529 // A notification exists for the given record
5530 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5531 assertEquals(1, notifsBefore.length);
5532
5533 reset(mPackageManager);
5534
5535 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5536
5537 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Aran Ink979c9762019-10-24 16:09:45 -04005538 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005539
5540 // Grant permission called for the UID of SystemUI under the target user ID
5541 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5542 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5543 eq(nr.sbn.getUserId()));
5544 }
5545
5546 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005547 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
5548 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5549 waitForIdle();
5550
5551 // No notifications exist for the given record
5552 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5553 assertEquals(0, notifsBefore.length);
5554
5555 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5556 int uid = 0; // sysui on primary user
5557
5558 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5559 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5560
5561 // Grant permission still called if no NotificationRecord exists for the given key
5562 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5563 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5564 eq(nr.sbn.getUserId()));
5565 }
5566
5567 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005568 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
5569 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5570 NotificationRecord nr =
5571 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
5572 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5573 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5574 waitForIdle();
5575
5576 // A notification exists for the given record
5577 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5578 assertEquals(1, notifsBefore.length);
5579
5580 reset(mPackageManager);
5581
5582 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5583
5584 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Aran Ink979c9762019-10-24 16:09:45 -04005585 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005586
5587 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5588 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5589 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5590 eq(UserHandle.USER_SYSTEM));
5591 }
5592
5593 @Test
5594 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
5595 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5596 int otherUserId = 11;
5597 NotificationRecord nr =
5598 generateNotificationRecord(mTestNotificationChannel, otherUserId);
5599 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5600 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5601 waitForIdle();
5602
5603 // A notification exists for the given record
5604 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5605 assertEquals(1, notifsBefore.length);
5606
5607 reset(mPackageManager);
5608
5609 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5610
5611 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04005612 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04005613 String sysuiPackage = "sysui";
5614 final String[] sysuiPackages = new String[] { sysuiPackage };
5615 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
5616
5617 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
5618 // time this is called
5619 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
5620 .thenReturn(otherUserUid);
5621
Aran Ink979c9762019-10-24 16:09:45 -04005622 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5623 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005624
5625 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5626 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5627 eq(otherUserUid), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5628 eq(otherUserId));
5629 }
5630
5631 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005632 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
5633 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5634 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005635
Aran Ink979c9762019-10-24 16:09:45 -04005636 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5637 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005638
Aran Ink979c9762019-10-24 16:09:45 -04005639 // create an inline record with two uris in it
5640 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5641 nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5642 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5643 nr.getKey(), uri2, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005644
Aran Ink979c9762019-10-24 16:09:45 -04005645 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5646 assertNotNull(record); // record exists
5647 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04005648
Aran Ink979c9762019-10-24 16:09:45 -04005649 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5650
5651 // permissionOwner destroyed
5652 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5653 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
5654 }
5655
5656
5657 @Test
5658 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
5659 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5660 reset(mPackageManager);
5661
5662 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5663
5664 // no permissionOwner destroyed
5665 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
5666 any(), eq(null), eq(~0), eq(nr.getUserId()));
5667 }
5668
5669 @Test
5670 public void testClearInlineReplyUriPermission_userAll() throws Exception {
5671 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5672 UserHandle.USER_ALL);
5673 reset(mPackageManager);
5674
5675 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5676 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
5677
5678 // create an inline record a uri in it
5679 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5680 nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5681
5682 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5683 assertNotNull(record); // record exists
5684
5685 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5686
5687 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
5688 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5689 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005690 }
5691
5692 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005693 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5694 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005695 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005696
Mady Mellor9e923e12019-12-17 16:08:46 -08005697 // And we are low ram
5698 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5699
5700 // Notification that would typically bubble
5701 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5702 "testNotificationBubbles_disabled_lowRamDevice");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005703 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005704 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5705 waitForIdle();
5706
Mady Mellor9e923e12019-12-17 16:08:46 -08005707 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005708 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5709 assertEquals(1, notifsAfter.length);
5710 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005711 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04005712
5713 @Test
5714 public void testRemoveLargeRemoteViews() throws Exception {
5715 int removeSize = mContext.getResources().getInteger(
5716 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
5717
5718 RemoteViews rv = mock(RemoteViews.class);
5719 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
5720 when(rv.clone()).thenReturn(rv);
5721 RemoteViews rv1 = mock(RemoteViews.class);
5722 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
5723 when(rv1.clone()).thenReturn(rv1);
5724 RemoteViews rv2 = mock(RemoteViews.class);
5725 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
5726 when(rv2.clone()).thenReturn(rv2);
5727 RemoteViews rv3 = mock(RemoteViews.class);
5728 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
5729 when(rv3.clone()).thenReturn(rv3);
5730 RemoteViews rv4 = mock(RemoteViews.class);
5731 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
5732 when(rv4.clone()).thenReturn(rv4);
5733 // note: different!
5734 RemoteViews rv5 = mock(RemoteViews.class);
5735 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
5736 when(rv5.clone()).thenReturn(rv5);
5737
5738 Notification np = new Notification.Builder(mContext, "test")
5739 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5740 .setContentText("test")
5741 .setCustomContentView(rv)
5742 .setCustomBigContentView(rv1)
5743 .setCustomHeadsUpContentView(rv2)
5744 .build();
5745 Notification n = new Notification.Builder(mContext, "test")
5746 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5747 .setContentText("test")
5748 .setCustomContentView(rv3)
5749 .setCustomBigContentView(rv4)
5750 .setCustomHeadsUpContentView(rv5)
5751 .setPublicVersion(np)
5752 .build();
5753
5754 assertNotNull(np.contentView);
5755 assertNotNull(np.bigContentView);
5756 assertNotNull(np.headsUpContentView);
5757
5758 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
5759 assertNotNull(n.publicVersion.contentView);
5760 assertNotNull(n.publicVersion.bigContentView);
5761 assertNotNull(n.publicVersion.headsUpContentView);
5762
5763 mService.fixNotification(n, PKG, "tag", 9, 0);
5764
5765 assertNull(n.contentView);
5766 assertNull(n.bigContentView);
5767 assertNotNull(n.headsUpContentView);
5768 assertNull(n.publicVersion.contentView);
5769 assertNull(n.publicVersion.bigContentView);
5770 assertNull(n.publicVersion.headsUpContentView);
5771
5772 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
5773 }
Mady Mellor06b770c2019-08-29 18:01:00 -07005774
Colin Cross5ea7fb72019-12-18 17:16:36 -08005775 @Test
Mady Mellora7731962019-06-17 17:57:02 -07005776 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
5777 throws Exception {
5778 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005779 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07005780
Mady Mellor9e923e12019-12-17 16:08:46 -08005781 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5782 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
5783 // Modify metadata flags
5784 nr.sbn.getNotification().getBubbleMetadata().setFlags(
5785 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
5786 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07005787
5788 // Ensure we're not foreground
5789 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5790 IMPORTANCE_VISIBLE);
5791
Mady Mellor9e923e12019-12-17 16:08:46 -08005792 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora7731962019-06-17 17:57:02 -07005793 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5794 waitForIdle();
5795
5796 // yes allowed, yes messaging, yes bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005797 Notification notif = mService.getNotificationRecord(nr.sbn.getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07005798 assertTrue(notif.isBubbleNotification());
5799
5800 // Our flags should have failed since we're not foreground
5801 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
5802 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
5803 }
5804
5805 @Test
5806 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
5807 throws RemoteException {
5808 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005809 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07005810
Mady Mellor9e923e12019-12-17 16:08:46 -08005811 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5812 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
5813 // Modify metadata flags
5814 nr.sbn.getNotification().getBubbleMetadata().setFlags(
5815 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
5816 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07005817
5818 // Ensure we are in the foreground
5819 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5820 IMPORTANCE_FOREGROUND);
5821
Mady Mellor9e923e12019-12-17 16:08:46 -08005822 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora7731962019-06-17 17:57:02 -07005823 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5824 waitForIdle();
5825
5826 // yes allowed, yes messaging, yes bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005827 Notification notif = mService.getNotificationRecord(nr.sbn.getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07005828 assertTrue(notif.isBubbleNotification());
5829
Mady Mellor9e923e12019-12-17 16:08:46 -08005830 // Our flags should have passed since we are foreground
Mady Mellora7731962019-06-17 17:57:02 -07005831 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
5832 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
5833 }
Mady Mellor22f2f072019-04-18 13:26:18 -07005834
5835 @Test
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08005836 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
5837 throws RemoteException {
5838 // Bubbles are allowed!
5839 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
5840
5841 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
5842 ArgumentCaptor.forClass(LauncherApps.Callback.class);
5843
5844 // Messaging notification with shortcut info
5845 Notification.BubbleMetadata metadata =
5846 getBubbleMetadataBuilder().createShortcutBubble("someshortcutId").build();
5847 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
5848 null /* groupKey */, false /* isSummary */);
5849 nb.setBubbleMetadata(metadata);
5850 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5851 "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
5852 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5853
5854 // Pretend the shortcut exists
5855 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
5856 shortcutInfos.add(mock(ShortcutInfo.class));
5857 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
5858
5859 // Test: Send the bubble notification
5860 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
5861 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5862 waitForIdle();
5863
5864 // Verify:
5865
5866 // Make sure we register the callback for shortcut changes
5867 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
5868
5869 // yes allowed, yes messaging w/shortcut, yes bubble
5870 Notification notif = mService.getNotificationRecord(nr.sbn.getKey()).getNotification();
5871 assertTrue(notif.isBubbleNotification());
5872
5873 // Test: Remove the shortcut
5874 launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
5875 new UserHandle(mUid));
5876
5877 // Verify:
5878
5879 // Make sure callback is unregistered
5880 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
5881
5882 // We're no longer a bubble
5883 Notification notif2 = mService.getNotificationRecord(nr.sbn.getKey()).getNotification();
5884 assertFalse(notif2.isBubbleNotification());
5885 }
5886
5887 @Test
Mady Mellor22f2f072019-04-18 13:26:18 -07005888 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
5889 throws Exception {
5890 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005891 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07005892
5893 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5894 true /* summaryAutoCancel */);
5895
5896 // Dismiss summary
5897 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5898 true);
5899 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(),
5900 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(),
5901 NotificationStats.DISMISSAL_SHADE,
5902 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
5903 waitForIdle();
5904
5905 // The bubble should still exist
5906 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5907 assertEquals(1, notifsAfter.length);
5908 }
5909
5910 @Test
5911 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
5912 throws Exception {
5913 // Bubbles are allowed!
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05005914 setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07005915
5916 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5917 true /* summaryAutoCancel */);
5918
5919 // Click summary
5920 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5921 true);
5922 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
5923 nrSummary.getKey(), nv);
5924 waitForIdle();
5925
5926 // The bubble should still exist
5927 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5928 assertEquals(1, notifsAfter.length);
5929 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04005930
5931 @Test
5932 public void testLoadDefaultApprovedServices_emptyResources() {
5933 TestableResources tr = mContext.getOrCreateTestableResources();
5934 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
5935 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
5936 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
5937 setDefaultAssistantInDeviceConfig("");
5938
5939 mService.loadDefaultApprovedServices(USER_SYSTEM);
5940
5941 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
5942 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
5943 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
5944 }
5945
5946 @Test
5947 public void testLoadDefaultApprovedServices_dnd() {
5948 TestableResources tr = mContext.getOrCreateTestableResources();
5949 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
5950 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
5951 .thenReturn(new ArraySet<>());
5952
5953 mService.loadDefaultApprovedServices(USER_SYSTEM);
5954
5955 verify(mConditionProviders, times(1)).addDefaultComponentOrPackage("test");
5956 }
5957
5958 // TODO: add tests for the rest of the non-empty cases
Julia Reynoldsb317ff72019-11-26 14:20:51 -05005959
5960 @Test
5961 public void testOnUnlockUser() {
5962 UserInfo ui = new UserInfo();
5963 ui.id = 10;
5964 mService.onUnlockUser(ui);
5965 waitForIdle();
5966
5967 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
5968 }
5969
5970 @Test
5971 public void testOnStopUser() {
5972 UserInfo ui = new UserInfo();
5973 ui.id = 10;
5974 mService.onStopUser(ui);
5975 waitForIdle();
5976
5977 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
5978 }
5979
5980 @Test
5981 public void testOnBootPhase() {
5982 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
5983
5984 verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
5985
5986 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
5987
5988 verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart();
5989 }
5990
5991 @Test
5992 public void testHandleOnPackageChanged() {
5993 String[] pkgs = new String[] {PKG, PKG_N_MR1};
5994 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
5995
5996 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
5997
5998 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
5999
6000 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
6001
6002 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
6003 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
6004 }
6005
6006 @Test
6007 public void testNotificationHistory_addNoisyNotification() throws Exception {
6008 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08006009 null /* tvExtender */);
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006010 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
6011 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
6012 waitForIdle();
6013
6014 verify(mHistoryManager, times(1)).addNotification(any());
6015 }
Julia Reynolds0f767342019-12-18 09:11:55 -05006016
6017 @Test
6018 public void createConversationNotificationChannel() throws Exception {
6019 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
6020 original.setAllowBubbles(!original.canBubble());
6021 original.setShowBadge(!original.canShowBadge());
6022
6023 Parcel parcel = Parcel.obtain();
6024 original.writeToParcel(parcel, 0);
6025 parcel.setDataPosition(0);
6026 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
6027 assertEquals(original, orig);
6028 assertFalse(TextUtils.isEmpty(orig.getName()));
6029
6030 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6031 orig)));
6032
Julia Reynolds7c267522020-01-16 11:26:41 -05006033 mBinderService.createConversationNotificationChannelForPackage(
6034 PKG, mUid, "key", orig, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006035
6036 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006037 PKG, 0, PKG, original.getId(), false, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006038
6039 assertEquals(original.getName(), friendChannel.getName());
6040 assertEquals(original.getId(), friendChannel.getParentChannelId());
6041 assertEquals("friend", friendChannel.getConversationId());
6042 assertEquals(null, original.getConversationId());
6043 assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
6044 assertEquals(original.canBubble(), friendChannel.canBubble());
6045 assertFalse(original.getId().equals(friendChannel.getId()));
6046 assertNotNull(friendChannel.getId());
6047 }
6048
6049 @Test
6050 public void deleteConversationNotificationChannels() throws Exception {
6051 NotificationChannel messagesParent =
6052 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
6053 Parcel msgParcel = Parcel.obtain();
6054 messagesParent.writeToParcel(msgParcel, 0);
6055 msgParcel.setDataPosition(0);
6056
6057 NotificationChannel callsParent =
6058 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
6059 Parcel callParcel = Parcel.obtain();
6060 callsParent.writeToParcel(callParcel, 0);
6061 callParcel.setDataPosition(0);
6062
6063 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6064 messagesParent, callsParent)));
6065
6066 String conversationId = "friend";
6067
6068 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006069 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
6070 conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006071 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006072 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
Julia Reynolds0f767342019-12-18 09:11:55 -05006073 conversationId);
6074
6075 NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006076 PKG, 0, PKG, messagesParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006077 NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006078 PKG, 0, PKG, callsParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006079
6080 assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
6081 assertEquals(conversationId, messagesChild.getConversationId());
6082
6083 assertEquals(callsParent.getId(), callsChild.getParentChannelId());
6084 assertEquals(conversationId, callsChild.getConversationId());
6085
6086 mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
6087
6088 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006089 PKG, 0, PKG, messagesParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006090 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006091 PKG, 0, PKG, callsParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006092 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05006093}