blob: 3cd0e92964ec1afb4b2660fc2cdce5108060126d [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;
Mady Mellorbe797962019-04-01 16:04:24 -070020import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
Mady Mellor22f2f072019-04-18 13:26:18 -070021import static android.app.Notification.FLAG_AUTO_CANCEL;
Mady Mellor49b1bf12019-03-29 12:00:02 -070022import static android.app.Notification.FLAG_BUBBLE;
Julia Reynoldse5c60452018-04-30 14:41:36 -040023import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
Mady Mellora92268c2020-03-09 17:25:08 -070024import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
25import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
26import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
27import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050028import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
Julia Reynolds27c0a962018-12-10 12:37:28 -050029import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040030import static android.app.NotificationManager.IMPORTANCE_HIGH;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040031import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050032import static android.app.NotificationManager.IMPORTANCE_MAX;
Julia Reynolds4da79702017-06-01 11:06:10 -040033import static android.app.NotificationManager.IMPORTANCE_NONE;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040034import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
Julia Reynolds24edc002020-01-29 16:35:32 -050035import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
36import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050037import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
38import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
39import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
40import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
41import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
42import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
43import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
44import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
45import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
Mady Mellora92268c2020-03-09 17:25:08 -070046import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Julia Reynoldse1816412017-10-24 10:39:11 -040047import static android.content.pm.PackageManager.FEATURE_WATCH;
Julia Reynolds4db59552017-06-30 13:34:01 -040048import static android.content.pm.PackageManager.PERMISSION_DENIED;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -040049import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050050import static android.os.Build.VERSION_CODES.O_MR1;
51import static android.os.Build.VERSION_CODES.P;
Julia Reynolds57a974b2019-10-07 11:51:47 -040052import static android.os.UserHandle.USER_SYSTEM;
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -040053import static android.service.notification.Adjustment.KEY_IMPORTANCE;
54import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
Tony Makeda84a72018-11-19 17:01:32 +000055import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
56import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040057
Geoffrey Pitsch03533712017-01-05 10:30:07 -050058import static junit.framework.Assert.assertEquals;
Julia Reynolds727a7282017-04-13 10:54:01 -040059import static junit.framework.Assert.assertFalse;
Julia Reynolds92febc32017-10-26 11:30:31 -040060import static junit.framework.Assert.assertNotNull;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040061import static junit.framework.Assert.assertNull;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050062import static junit.framework.Assert.assertTrue;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050063import static junit.framework.Assert.fail;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050064
Jay Aliomerfea80252019-11-20 18:14:24 -050065import static org.mockito.ArgumentMatchers.isNull;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -050066import static org.mockito.Matchers.anyBoolean;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -040067import static org.mockito.Matchers.anyLong;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050068import static org.mockito.Matchers.anyString;
69import static org.mockito.Matchers.eq;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050070import static org.mockito.Mockito.any;
71import static org.mockito.Mockito.anyInt;
Julia Reynoldsb6c83742019-07-30 18:03:40 -040072import static org.mockito.Mockito.clearInvocations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040073import static org.mockito.Mockito.doAnswer;
Julia Reynolds4afe2642019-05-01 08:42:24 -040074import static org.mockito.Mockito.doNothing;
Julia Reynoldsea58c202020-02-03 12:52:49 -050075import static org.mockito.Mockito.doThrow;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050076import static org.mockito.Mockito.mock;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040077import static org.mockito.Mockito.never;
78import static org.mockito.Mockito.reset;
Julia Reynolds503ed942017-10-04 16:04:56 -040079import static org.mockito.Mockito.spy;
80import static org.mockito.Mockito.timeout;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050081import static org.mockito.Mockito.times;
82import static org.mockito.Mockito.verify;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050083import static org.mockito.Mockito.when;
84
Julia Reynolds68263d12017-06-21 14:21:19 -040085import android.app.ActivityManager;
Mady Mellor13f9bc82020-03-24 19:09:28 -070086import android.app.ActivityManagerInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -040087import android.app.AppOpsManager;
Julia Reynoldsa94365d2019-04-09 10:48:43 -040088import android.app.AutomaticZenRule;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040089import android.app.IActivityManager;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050090import android.app.INotificationManager;
Julia Reynolds268647a2018-10-25 16:54:27 -040091import android.app.ITransientNotification;
92import android.app.IUriGrantsManager;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050093import android.app.Notification;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040094import android.app.Notification.MessagingStyle.Message;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050095import android.app.NotificationChannel;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040096import android.app.NotificationChannelGroup;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050097import android.app.NotificationManager;
Mady Mellor7eb18ef2019-03-27 14:03:46 -070098import android.app.PendingIntent;
Mady Mellorbe797962019-04-01 16:04:24 -070099import android.app.Person;
Mady Mellora10448e2019-04-26 13:50:58 -0700100import android.app.RemoteInput;
Yotam Aron74299972020-01-16 16:20:58 +0200101import android.app.StatsManager;
Jason Parks50322ff2018-03-27 10:23:33 -0500102import android.app.admin.DevicePolicyManagerInternal;
Julia Reynolds7217dc92018-03-07 12:12:09 -0500103import android.app.usage.UsageStatsManagerInternal;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400104import android.companion.ICompanionDeviceManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500105import android.content.ComponentName;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600106import android.content.ContentUris;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500107import android.content.Context;
Beverlyd4f96492017-08-02 13:36:11 -0400108import android.content.Intent;
Mady Mellora92268c2020-03-09 17:25:08 -0700109import android.content.pm.ActivityInfo;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500110import android.content.pm.ApplicationInfo;
111import android.content.pm.IPackageManager;
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800112import android.content.pm.LauncherApps;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500113import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500114import android.content.pm.ParceledListSlice;
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800115import android.content.pm.ShortcutInfo;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400116import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200117import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400118import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700119import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400120import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400121import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500122import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400123import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400124import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400125import android.os.IBinder;
Julia Reynolds0f767342019-12-18 09:11:55 -0500126import android.os.Parcel;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400127import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400128import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700129import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500130import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400131import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000132import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600133import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000134import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400135import android.service.notification.Adjustment;
Julia Reynolds882f2062020-02-05 12:11:38 -0500136import android.service.notification.ConversationChannelWrapper;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400137import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400138import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500139import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400140import android.service.notification.ZenPolicy;
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400141import android.telephony.TelephonyManager;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400142import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400143import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400144import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400145import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400146import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400147import android.testing.TestablePermissions;
Julia Reynolds57a974b2019-10-07 11:51:47 -0400148import android.testing.TestableResources;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400149import android.text.Html;
Julia Reynolds0f767342019-12-18 09:11:55 -0500150import android.text.TextUtils;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400151import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000152import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400153import android.util.AtomicFile;
Julia Reynolds469144c2019-06-21 14:30:28 -0400154import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400155import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400156
Mady Mellor49b1bf12019-03-29 12:00:02 -0700157import androidx.annotation.Nullable;
158import androidx.test.InstrumentationRegistry;
159
Tony Mak9a3c1f12019-03-04 16:04:42 +0000160import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Will Brockmancfd98302020-01-29 15:57:30 -0500161import com.android.internal.logging.InstanceIdSequence;
162import com.android.internal.logging.InstanceIdSequenceFake;
Julia Reynolds503ed942017-10-04 16:04:56 -0400163import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400164import com.android.internal.util.FastXmlSerializer;
Mady Mellor13f9bc82020-03-24 19:09:28 -0700165import com.android.server.DeviceIdleInternal;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700166import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400167import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500168import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400169import com.android.server.lights.LightsManager;
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100170import com.android.server.lights.LogicalLight;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400171import com.android.server.notification.NotificationManagerService.NotificationAssistants;
172import com.android.server.notification.NotificationManagerService.NotificationListeners;
Bernardo Rufino18725b62020-01-21 14:12:43 +0000173import com.android.server.statusbar.StatusBarManagerInternal;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700174import com.android.server.uri.UriGrantsManagerInternal;
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000175import com.android.server.wm.ActivityTaskManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400176import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400177
178import org.junit.After;
179import org.junit.Before;
180import org.junit.Test;
181import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500182import org.mockito.ArgumentCaptor;
183import org.mockito.Mock;
184import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400185import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400186import org.xmlpull.v1.XmlPullParser;
187import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500188
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400189import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400190import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400191import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400192import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400193import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400194import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400195import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500196import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000197import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400198import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400199import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200200import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500201
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400202
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400203@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400204@RunWith(AndroidTestingRunner.class)
205@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500206public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500207 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000208
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400209 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500210 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500211 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400212 private NotificationManagerInternal mInternalService;
Mady Mellor56515c42020-02-18 17:58:36 -0800213 private ShortcutHelper mShortcutHelper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400214 @Mock
215 private IPackageManager mPackageManager;
216 @Mock
217 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400218 @Mock
219 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400220 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500221 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400222 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400223 @Mock
224 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400225 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400226 AtomicFile mPolicyFile;
227 File mFile;
228 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400229 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400230 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400231 private UsageStatsManagerInternal mAppUsageStats;
232 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400233 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400234 @Mock
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800235 private LauncherApps mLauncherApps;
236 @Mock
Julia Reynolds68263d12017-06-21 14:21:19 -0400237 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200238 @Mock
239 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400240 @Mock
241 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400242
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500243 private static final int MAX_POST_DELAY = 1000;
244
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500245 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500246 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000247
248 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
249
Julia Reynoldsda781472017-04-12 09:41:16 -0400250 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400251 private NotificationListeners mListeners;
252 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400253 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400254 private ManagedServices.ManagedServiceInfo mListener;
255 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400256 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400257 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400258 @Mock
259 IBinder mPermOwner;
260 @Mock
261 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700262 @Mock
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000263 ActivityTaskManagerInternal mAtm;
264 @Mock
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700265 IUriGrantsManager mUgm;
266 @Mock
267 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400268 @Mock
269 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000270 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000271 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
272 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400273 @Mock
274 UserManager mUm;
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500275 @Mock
276 NotificationHistoryManager mHistoryManager;
Yotam Aron74299972020-01-16 16:20:58 +0200277 @Mock
278 StatsManager mStatsManager;
Will Brockman2b6959e2020-01-22 09:59:50 -0500279 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
Will Brockmancfd98302020-01-29 15:57:30 -0500280 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
281 1 << 30);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000282 @Mock
283 StatusBarManagerInternal mStatusBar;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500284
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400285 // Use a Testable subclass so we can simulate calls from the system without failing.
286 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500287 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700288 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000289 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000290 @Nullable
291 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500292
Will Brockmancfd98302020-01-29 15:57:30 -0500293 TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
294 InstanceIdSequence notificationInstanceIdSequence) {
295 super(context, logger, notificationInstanceIdSequence);
Amith Yamasani803eab692017-11-09 17:47:04 -0800296 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400297
Mady Mellor56515c42020-02-18 17:58:36 -0800298 RankingHelper getRankingHelper() {
299 return mRankingHelper;
300 }
301
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400302 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400303 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500304 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700305 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400306 }
307
308 @Override
309 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500310 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700311 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400312 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400313
314 @Override
315 protected ICompanionDeviceManager getCompanionManager() {
316 return null;
317 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800318
319 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800320 protected void reportUserInteraction(NotificationRecord r) {
321 return;
322 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500323
324 @Override
325 protected void handleSavePolicyFile() {
326 return;
327 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000328
329 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000330 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
331 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000332 countLogSmartSuggestionsVisible++;
333 }
334
Annie Meng8b646fd2019-02-01 18:46:42 +0000335 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000336 protected void setNotificationAssistantAccessGrantedForUserInternal(
337 ComponentName assistant, int userId, boolean granted) {
338 if (mNotificationAssistantAccessGrantedCallback != null) {
339 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
340 return;
341 }
342 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
343 }
344
345 private void setNotificationAssistantAccessGrantedCallback(
346 @Nullable NotificationAssistantAccessGrantedCallback callback) {
347 this.mNotificationAssistantAccessGrantedCallback = callback;
348 }
349
350 interface NotificationAssistantAccessGrantedCallback {
351 void onGranted(ComponentName assistant, int userId, boolean granted);
352 }
Mady Mellor56515c42020-02-18 17:58:36 -0800353 }
354
Beverly58b24532018-10-02 09:08:23 -0400355 private class TestableToastCallback extends ITransientNotification.Stub {
356 @Override
357 public void show(IBinder windowToken) {
358 }
359
360 @Override
361 public void hide() {
362 }
363 }
364
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500365 @Before
366 public void setUp() throws Exception {
Beverly24d103b2020-02-18 17:40:57 -0500367 // Shell permisssions will override permissions of our app, so add all necessary permissions
Beverly080782f2020-02-24 16:42:57 -0500368 // for this test here:
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000369 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Beverly24d103b2020-02-18 17:40:57 -0500370 "android.permission.WRITE_DEVICE_CONFIG",
371 "android.permission.READ_DEVICE_CONFIG",
372 "android.permission.READ_CONTACTS");
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000373
Julia Reynoldsda781472017-04-12 09:41:16 -0400374 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400375
Mady Mellor13f9bc82020-03-24 19:09:28 -0700376 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
377 when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
378 ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
379
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700380 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
381 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400382 LocalServices.removeServiceForTest(WindowManagerInternal.class);
383 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000384 LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
385 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
Mady Mellor13f9bc82020-03-24 19:09:28 -0700386 LocalServices.removeServiceForTest(DeviceIdleInternal.class);
387 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
388 LocalServices.removeServiceForTest(ActivityManagerInternal.class);
389 LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700390
Julia Reynolds4afe2642019-05-01 08:42:24 -0400391 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
392
Will Brockmancfd98302020-01-29 15:57:30 -0500393 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
394 mNotificationInstanceIdSequence);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500395
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400396 // Use this testable looper.
397 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500398 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400399 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400400
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400401 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400402 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
403 Object[] args = invocation.getArguments();
404 return getApplicationInfo((String) args[0], mUid);
405 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500406 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400407 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
408 Object[] args = invocation.getArguments();
409 return getApplicationInfo((String) args[0], mUid);
410 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400411 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500412 final LightsManager mockLightsManager = mock(LightsManager.class);
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100413 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400414 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400415 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700416 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400417 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400418 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400419 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500420
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400421 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400422 mFile = new File(mContext.getCacheDir(), "test.xml");
423 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400424 final String preupgradeXml = "<notification-policy></notification-policy>";
425 mPolicyFile = new AtomicFile(mFile);
426 FileOutputStream fos = mPolicyFile.startWrite();
427 fos.write(preupgradeXml.getBytes());
428 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400429
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400430 // Setup managed services
431 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400432 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400433 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
434 ArraySet<ComponentName> components = new ArraySet<>();
435 components.add(defaultComponent);
436 when(mListeners.getDefaultComponents()).thenReturn(components);
437 when(mConditionProviders.getDefaultPackages())
438 .thenReturn(new ArraySet<>(Arrays.asList("config")));
439 when(mAssistants.getDefaultComponents()).thenReturn(components);
440 when(mAssistants.queryPackageForServices(
441 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400442 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
443 ManagedServices.Config listenerConfig = new ManagedServices.Config();
444 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
445 when(mListeners.getConfig()).thenReturn(listenerConfig);
446 ManagedServices.Config assistantConfig = new ManagedServices.Config();
447 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
448 when(mAssistants.getConfig()).thenReturn(assistantConfig);
449 ManagedServices.Config dndConfig = new ManagedServices.Config();
450 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
451 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
452
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400453 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
454
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500455 mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
456 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400457 mListeners, mAssistants, mConditionProviders,
458 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000459 mGroupHelper, mAm, mAtm, mAppUsageStats,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400460 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400461 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
462 mock(TelephonyManager.class));
Julia Reynolds4afe2642019-05-01 08:42:24 -0400463 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
464
Julia Reynolds503ed942017-10-04 16:04:56 -0400465 mService.setAudioManager(mAudioManager);
Mady Mellor56515c42020-02-18 17:58:36 -0800466
467 mShortcutHelper = mService.getShortcutHelper();
468 mShortcutHelper.setLauncherApps(mLauncherApps);
469
470 // Set the testable bubble extractor
471 RankingHelper rankingHelper = mService.getRankingHelper();
472 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
Mady Mellora92268c2020-03-09 17:25:08 -0700473 extractor.setActivityManager(mActivityManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500474
475 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400476 mBinderService = mService.getBinderService();
477 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500478
479 mBinderService.createNotificationChannels(
480 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400481 assertNotNull(mBinderService.getNotificationChannel(
482 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400483 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500484 }
485
Julia Reynoldsb852e562017-06-06 16:14:18 -0400486 @After
Will Brockman9918db92020-03-06 16:48:39 -0500487 public void assertNotificationRecordLoggerCallsValid() {
488 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
489 if (call.wasLogged) {
490 assertNotNull(call.event);
491 }
492 }
493 }
494
495 @After
Julia Reynoldsb852e562017-06-06 16:14:18 -0400496 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400497 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000498 clearDeviceConfig();
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500499 mService.unregisterDeviceConfigChange();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000500 InstrumentationRegistry.getInstrumentation()
501 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400502 }
503
Jay Aliomer4204f252019-08-26 11:36:53 -0400504 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
505 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
506 changed.put(true, new ArrayList<>());
507 changed.put(false, new ArrayList<>());
508 return changed;
509 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400510 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
511 final ApplicationInfo applicationInfo = new ApplicationInfo();
512 applicationInfo.uid = uid;
513 switch (pkg) {
514 case PKG_N_MR1:
515 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
516 break;
517 case PKG_O:
518 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
519 break;
520 case PKG_P:
521 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
522 break;
523 default:
524 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
525 break;
526 }
527 return applicationInfo;
528 }
529
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500530 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400531 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500532 }
533
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500534 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
Mady Mellora92268c2020-03-09 17:25:08 -0700535 int pkgPref, boolean channelEnabled) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500536 Settings.Global.putInt(mContext.getContentResolver(),
537 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
538 mService.mPreferencesHelper.updateBubblesEnabled();
539 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled());
540 try {
Mady Mellora92268c2020-03-09 17:25:08 -0700541 mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500542 } catch (RemoteException e) {
543 e.printStackTrace();
544 }
Mady Mellorc6820342019-05-20 12:04:36 -0700545 mTestNotificationChannel.setAllowBubbles(channelEnabled);
546 }
547
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500548 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
549 Notification.Builder nb = new Notification.Builder(mContext, "a")
550 .setContentTitle("foo")
551 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400552 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
553 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500554 nb.build(), new UserHandle(userId), null, postTime);
555 return sbn;
556 }
557
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400558 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
559 String groupKey, boolean isSummary) {
560 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
561 .setContentTitle("foo")
562 .setSmallIcon(android.R.drawable.sym_def_app_icon)
563 .setGroup(groupKey)
564 .setGroupSummary(isSummary);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400565 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
566 "tag" + System.currentTimeMillis(), mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400567 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000568 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400569 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400570
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500571 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500572 return generateNotificationRecord(channel, null);
573 }
574
575 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
576 Notification.TvExtender extender) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500577 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500578 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500579 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500580 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500581 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500582 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500583 if (extender != null) {
584 nb.extend(extender);
585 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400586 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400587 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000588 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500589 }
590
Aran Inkfd2bfd32019-10-04 16:30:01 -0400591 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
592 if (channel == null) {
593 channel = mTestNotificationChannel;
594 }
595 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
596 .setContentTitle("foo")
597 .setSmallIcon(android.R.drawable.sym_def_app_icon);
598 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
599 nb.build(), new UserHandle(userId), null, 0);
600 return new NotificationRecord(mContext, sbn, channel);
601 }
602
Mady Mellor9e923e12019-12-17 16:08:46 -0800603 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
604 String tag) {
605 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
606 }
607
608 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
609 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
610 if (channel == null) {
611 channel = mTestNotificationChannel;
612 }
613 if (tag == null) {
614 tag = "tag";
615 }
616 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
617 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
618 tag, mUid, 0,
619 nb.build(), new UserHandle(mUid), null, 0);
620 return new NotificationRecord(mContext, sbn, channel);
621 }
622
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400623 private Map<String, Answer> getSignalExtractorSideEffects() {
624 Map<String, Answer> answers = new ArrayMap<>();
625
626 answers.put("override group key", invocationOnMock -> {
627 ((NotificationRecord) invocationOnMock.getArguments()[0])
628 .setOverrideGroupKey("bananas");
629 return null;
630 });
631 answers.put("override people", invocationOnMock -> {
632 ((NotificationRecord) invocationOnMock.getArguments()[0])
633 .setPeopleOverride(new ArrayList<>());
634 return null;
635 });
636 answers.put("snooze criteria", invocationOnMock -> {
637 ((NotificationRecord) invocationOnMock.getArguments()[0])
638 .setSnoozeCriteria(new ArrayList<>());
639 return null;
640 });
641 answers.put("notification channel", invocationOnMock -> {
642 ((NotificationRecord) invocationOnMock.getArguments()[0])
643 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
644 return null;
645 });
646 answers.put("badging", invocationOnMock -> {
647 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
648 r.setShowBadge(!r.canShowBadge());
649 return null;
650 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500651 answers.put("bubbles", invocationOnMock -> {
652 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
653 r.setAllowBubble(!r.canBubble());
654 return null;
655 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400656 answers.put("package visibility", invocationOnMock -> {
657 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
658 Notification.VISIBILITY_SECRET);
659 return null;
660 });
661
662 return answers;
663 }
664
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400665 private void clearDeviceConfig() {
666 DeviceConfig.resetToDefaults(
667 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
668 }
669
670 private void setDefaultAssistantInDeviceConfig(String componentName) {
671 DeviceConfig.setProperty(
672 DeviceConfig.NAMESPACE_SYSTEMUI,
673 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
674 componentName,
675 false);
676 }
677
Mady Mellor9e923e12019-12-17 16:08:46 -0800678 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
679 String groupKey, boolean isSummary) {
680 // Give it a person
681 Person person = new Person.Builder()
682 .setName("bubblebot")
683 .build();
Mady Mellor9e923e12019-12-17 16:08:46 -0800684 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
685 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
686 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
687 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
688 inputIntent).addRemoteInput(remoteInput)
689 .build();
690 // Make it messaging style
691 Notification.Builder nb = new Notification.Builder(mContext,
692 mTestNotificationChannel.getId())
693 .setContentTitle("foo")
694 .setStyle(new Notification.MessagingStyle(person)
695 .setConversationTitle("Bubble Chat")
696 .addMessage("Hello?",
697 SystemClock.currentThreadTimeMillis() - 300000, person)
698 .addMessage("Is it me you're looking for?",
699 SystemClock.currentThreadTimeMillis(), person)
700 )
701 .setActions(replyAction)
702 .setSmallIcon(android.R.drawable.sym_def_app_icon)
703 .setGroupSummary(isSummary);
704 if (groupKey != null) {
705 nb.setGroup(groupKey);
706 }
707 if (addBubbleMetadata) {
Mady Mellora92268c2020-03-09 17:25:08 -0700708 nb.setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -0800709 }
710 return nb;
711 }
712
Mady Mellora92268c2020-03-09 17:25:08 -0700713 private Notification.BubbleMetadata getBubbleMetadata() {
714 PendingIntent pendingIntent = mock(PendingIntent.class);
715 Intent intent = mock(Intent.class);
716 when(pendingIntent.getIntent()).thenReturn(intent);
717
718 ActivityInfo info = new ActivityInfo();
719 info.resizeMode = RESIZE_MODE_RESIZEABLE;
720 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
721
722 return new Notification.BubbleMetadata.Builder(
723 pendingIntent,
724 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
725 .build();
726 }
727
Mady Mellor22f2f072019-04-18 13:26:18 -0700728 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
729 throws RemoteException {
730
Mady Mellor9e923e12019-12-17 16:08:46 -0800731 String groupKey = "BUBBLE_GROUP";
Mady Mellor22f2f072019-04-18 13:26:18 -0700732
Mady Mellor9e923e12019-12-17 16:08:46 -0800733 // Notification that has bubble metadata
734 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
735 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
Mady Mellor22f2f072019-04-18 13:26:18 -0700736
Julia Reynolds24edc002020-01-29 16:35:32 -0500737 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
738 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
739 nrBubble.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700740 waitForIdle();
741
742 // Make sure we are a bubble
743 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
744 assertEquals(1, notifsAfter.length);
745 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
746
Mady Mellor9e923e12019-12-17 16:08:46 -0800747 // Notification without bubble metadata
748 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
749 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
750
Julia Reynolds24edc002020-01-29 16:35:32 -0500751 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
752 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
753 nrPlain.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700754 waitForIdle();
755
756 notifsAfter = mBinderService.getActiveNotifications(PKG);
757 assertEquals(2, notifsAfter.length);
758
759 // Summary notification for both of those
Mady Mellor9e923e12019-12-17 16:08:46 -0800760 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
761 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
762
Mady Mellor22f2f072019-04-18 13:26:18 -0700763 if (summaryAutoCancel) {
764 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
765 }
Julia Reynolds24edc002020-01-29 16:35:32 -0500766 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
767 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
768 nrSummary.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700769 waitForIdle();
770
771 notifsAfter = mBinderService.getActiveNotifications(PKG);
772 assertEquals(3, notifsAfter.length);
773
774 return nrSummary;
775 }
776
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500777 @Test
Jay Aliomerfea80252019-11-20 18:14:24 -0500778 public void testDefaultAssistant_overrideDefault() {
779 final int userId = 0;
780 final String testComponent = "package/class";
781 final List<UserInfo> userInfos = new ArrayList<>();
782 userInfos.add(new UserInfo(0, "", 0));
783 final ArraySet<ComponentName> validAssistants = new ArraySet<>();
784 validAssistants.add(ComponentName.unflattenFromString(testComponent));
785 final String originalComponent = DeviceConfig.getProperty(
786 DeviceConfig.NAMESPACE_SYSTEMUI,
787 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE
788 );
789 DeviceConfig.setProperty(
790 DeviceConfig.NAMESPACE_SYSTEMUI,
791 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
792 testComponent,
793 false
794 );
795 when(mActivityManager.isLowRamDevice()).thenReturn(false);
796 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
797 .thenReturn(validAssistants);
798 when(mAssistants.getDefaultComponents()).thenReturn(new ArraySet<>());
799 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
800
801 mService.setDefaultAssistantForUser(userId);
802
803 verify(mAssistants).setPackageOrComponentEnabled(
804 eq(testComponent), eq(userId), eq(true), eq(true));
805
806 DeviceConfig.setProperty(
807 DeviceConfig.NAMESPACE_SYSTEMUI,
808 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
809 originalComponent,
810 false
811 );
812 }
813
814 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500815 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500816 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500817 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400818 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500819 new ParceledListSlice(Arrays.asList(channel)));
820 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400821 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500822 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500823 }
824
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500825 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500826 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500827 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400828 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200829 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500830 fail("Exception should be thrown immediately.");
831 } catch (NullPointerException e) {
832 // pass
833 }
834 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500835
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500836 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500837 public void testCreateNotificationChannels_TwoChannels() throws Exception {
838 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500839 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500840 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500841 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400842 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500843 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400844 assertTrue(mBinderService.getNotificationChannel(
845 PKG, mContext.getUserId(), PKG, "id1") != null);
846 assertTrue(mBinderService.getNotificationChannel(
847 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500848 }
849
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500850 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400851 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
852 throws Exception {
853 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500854 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400855 mBinderService.createNotificationChannels(PKG,
856 new ParceledListSlice(Arrays.asList(channel)));
857
858 // Recreating the channel doesn't throw, but ignores importance.
859 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400860 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400861 mBinderService.createNotificationChannels(PKG,
862 new ParceledListSlice(Arrays.asList(dupeChannel)));
863 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400864 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500865 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400866 }
867
868 @Test
869 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
870 throws Exception {
871 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500872 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400873 mBinderService.createNotificationChannels(PKG,
874 new ParceledListSlice(Arrays.asList(channel)));
875
876 // Recreating with a lower importance is allowed to modify the channel.
877 final NotificationChannel dupeChannel =
878 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
879 mBinderService.createNotificationChannels(PKG,
880 new ParceledListSlice(Arrays.asList(dupeChannel)));
881 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400882 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400883 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
884 }
885
886 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400887 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
888 throws Exception {
889 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500890 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400891 mBinderService.createNotificationChannels(PKG,
892 new ParceledListSlice(Arrays.asList(channel)));
893
894 // The user modifies importance directly, can no longer be changed by the app.
895 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400896 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400897 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
898
899 // Recreating with a lower importance leaves channel unchanged.
900 final NotificationChannel dupeChannel =
901 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
902 mBinderService.createNotificationChannels(PKG,
903 new ParceledListSlice(Arrays.asList(dupeChannel)));
904 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400905 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400906 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400907 }
908
909 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500910 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
911 throws Exception {
912 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500913 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500914 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400915 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400916 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500917 new ParceledListSlice(Arrays.asList(channel1, channel2)));
918 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400919 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500920 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500921 }
922
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500923 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500924 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500925 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
926
927 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400928 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500929 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400930
931 // isBlocked is only used for user blocking, not app suspension
932 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500933 }
934
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500935 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500936 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500937 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
938
939 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400940 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500941 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400942 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400943 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400944
945 mBinderService.createNotificationChannels(
946 PKG, new ParceledListSlice(Arrays.asList(channel)));
Julia Reynolds24edc002020-01-29 16:35:32 -0500947 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400948 mBinderService.enqueueNotificationWithTag(PKG, PKG,
949 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400950 sbn.getId(), sbn.getNotification(), sbn.getUserId());
951 waitForIdle();
952 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
953 }
954
955 @Test
956 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
957 throws Exception {
958 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
959
960 NotificationChannel channel = new NotificationChannel("blocked", "name",
961 NotificationManager.IMPORTANCE_NONE);
962 mBinderService.createNotificationChannels(
963 PKG, new ParceledListSlice(Arrays.asList(channel)));
964
Julia Reynolds24edc002020-01-29 16:35:32 -0500965 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -0400966 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400967 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400968 sbn.getId(), sbn.getNotification(), sbn.getUserId());
969 waitForIdle();
970 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
971 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400972 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400973 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
974 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400975 }
976
977 @Test
978 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
979 throws Exception {
980 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
981
982 NotificationChannel channel =
983 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
984 mBinderService.createNotificationChannels(
985 PKG, new ParceledListSlice(Arrays.asList(channel)));
986
987 NotificationChannel update =
988 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
989 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
990 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400991 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
992 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400993
Julia Reynolds24edc002020-01-29 16:35:32 -0500994 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -0400995 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400996 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400997 sbn.getId(), sbn.getNotification(), sbn.getUserId());
998 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700999 // The first time a foreground service notification is shown, we allow the channel
1000 // to be updated to allow it to be seen.
1001 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1002 assertEquals(IMPORTANCE_LOW,
1003 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001004 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1005 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -04001006 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001007 waitForIdle();
1008
1009 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1010 update.setFgServiceShown(true);
1011 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1012 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001013 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1014 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001015
Julia Reynolds24edc002020-01-29 16:35:32 -05001016 sbn = generateNotificationRecord(channel).getSbn();
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001017 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001018 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1019 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001020 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1021 waitForIdle();
1022 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001023 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001024 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001025 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1026 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001027 }
1028
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001029 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -04001030 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1031 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001032 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001033 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1034 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -04001035
1036 NotificationChannel channel = new NotificationChannel("id", "name",
1037 NotificationManager.IMPORTANCE_HIGH);
1038 channel.setGroup("something");
1039 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -04001040 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -04001041 verify(mUsageStats, times(1)).registerBlocked(eq(r));
1042 }
1043
1044 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -04001045 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001046 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1047
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001048 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -04001049
Julia Reynolds24edc002020-01-29 16:35:32 -05001050 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001051 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1052 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -04001053 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1054 waitForIdle();
1055 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001056 }
1057
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001058 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001059 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1060 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1061
1062 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1063
Julia Reynolds24edc002020-01-29 16:35:32 -05001064 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001065 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001066 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1067 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001068 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1069 waitForIdle();
1070 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001071 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001072 }
1073
Brad Stenning8c991ea2018-07-31 13:33:01 -07001074 /**
1075 * Confirm the system user on automotive devices can use car categories
1076 */
1077 @Test
1078 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
1079 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1080 .thenReturn(true);
1081 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1082 Notification.CATEGORY_CAR_WARNING,
1083 Notification.CATEGORY_CAR_INFORMATION);
1084 int id = 0;
1085 for (String category: categories) {
1086 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001087 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001088 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001089 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1090 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001091 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1092 }
1093 waitForIdle();
1094 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1095 }
1096
1097
1098 /**
1099 * Confirm restricted notification categories only apply to automotive.
1100 */
1101 @Test
1102 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1103 mService.isSystemUid = false;
1104 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1105 .thenReturn(false);
1106 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1107 Notification.CATEGORY_CAR_WARNING,
1108 Notification.CATEGORY_CAR_INFORMATION);
1109 int id = 0;
1110 for (String category: categories) {
1111 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001112 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001113 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001114 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1115 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001116 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1117 }
1118 waitForIdle();
1119 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1120 }
1121
1122 /**
1123 * Confirm if a non-system user tries to use the car categories on a automotive device that
1124 * they will get a security exception
1125 */
1126 @Test
1127 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1128 mService.isSystemUid = false;
1129 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1130 .thenReturn(true);
1131 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1132 Notification.CATEGORY_CAR_WARNING,
1133 Notification.CATEGORY_CAR_INFORMATION);
1134 for (String category: categories) {
Julia Reynolds24edc002020-01-29 16:35:32 -05001135 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001136 sbn.getNotification().category = category;
1137 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001138 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1139 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001140 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1141 fail("Calls from non system apps should not allow use of restricted categories");
1142 } catch (SecurityException e) {
1143 // pass
1144 }
1145 }
1146 waitForIdle();
1147 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1148 }
1149
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001150 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001151 public void testBlockedNotifications_blockedByAssistant() throws Exception {
1152 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001153 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001154
1155 NotificationChannel channel = new NotificationChannel("id", "name",
1156 NotificationManager.IMPORTANCE_HIGH);
1157 NotificationRecord r = generateNotificationRecord(channel);
1158 mService.addEnqueuedNotification(r);
1159
Julia Reynolds27c0a962018-12-10 12:37:28 -05001160 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001161 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001162 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05001163 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05001164 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001165
1166 NotificationManagerService.PostNotificationRunnable runnable =
1167 mService.new PostNotificationRunnable(r.getKey());
1168 runnable.run();
1169 waitForIdle();
1170
1171 verify(mUsageStats, never()).registerPostedByApp(any());
1172 }
1173
1174 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001175 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001176 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1177 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001178 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001179 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001180 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001181 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001182 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001183 }
1184
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001185 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001186 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
Will Brockman2b6959e2020-01-22 09:59:50 -05001187 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1188 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1189 generateNotificationRecord(null).getNotification(), 0);
1190 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001191 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001192
Will Brockman2b6959e2020-01-22 09:59:50 -05001193 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
Will Brockman9918db92020-03-06 16:48:39 -05001194 assertTrue(call.wasLogged);
Will Brockman75c60572020-01-31 10:30:27 -05001195 assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1196 call.event);
Will Brockman2b6959e2020-01-22 09:59:50 -05001197 assertNotNull(call.r);
1198 assertNull(call.old);
1199 assertEquals(0, call.position);
1200 assertEquals(0, call.buzzBeepBlink);
Julia Reynolds24edc002020-01-29 16:35:32 -05001201 assertEquals(PKG, call.r.getSbn().getPackageName());
1202 assertEquals(0, call.r.getSbn().getId());
1203 assertEquals(tag, call.r.getSbn().getTag());
Will Brockman4f0f9d22020-02-23 21:18:11 -05001204 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order
Will Brockman2b6959e2020-01-22 09:59:50 -05001205 }
1206
1207 @Test
1208 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1209 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1210 Notification original = new Notification.Builder(mContext,
1211 mTestNotificationChannel.getId())
1212 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1213 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1214 Notification update = new Notification.Builder(mContext,
1215 mTestNotificationChannel.getId())
1216 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1217 .setCategory(Notification.CATEGORY_ALARM).build();
1218 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1219 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001220 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001221
Will Brockman9918db92020-03-06 16:48:39 -05001222 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001223 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001224 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001225 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001226 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001227
Will Brockman9918db92020-03-06 16:48:39 -05001228 assertTrue(mNotificationRecordLogger.get(1).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001229 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001230 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED,
Will Brockman9918db92020-03-06 16:48:39 -05001231 mNotificationRecordLogger.event(1));
Will Brockmancfd98302020-01-29 15:57:30 -05001232 // Instance ID doesn't change on update of an active notification
Will Brockman4f0f9d22020-02-23 21:18:11 -05001233 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman2b6959e2020-01-22 09:59:50 -05001234 }
1235
1236 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001237 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1238 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
Will Brockman2b6959e2020-01-22 09:59:50 -05001239 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1240 generateNotificationRecord(null).getNotification(), 0);
1241 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1242 generateNotificationRecord(null).getNotification(), 0);
1243 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001244 assertEquals(2, mNotificationRecordLogger.numCalls());
1245 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockmand3d49332020-02-10 19:43:03 -05001246 assertEquals(
1247 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001248 mNotificationRecordLogger.event(0));
1249 assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1250 assertNull(mNotificationRecordLogger.event(1));
Will Brockmand3d49332020-02-10 19:43:03 -05001251 }
1252
1253 @Test
1254 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1255 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1256 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1257 generateNotificationRecord(null).getNotification(),
1258 0);
1259 final Notification notif = generateNotificationRecord(null).getNotification();
1260 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1261 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1262 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001263 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001264 assertEquals(
1265 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001266 mNotificationRecordLogger.event(0));
1267 assertNull(mNotificationRecordLogger.event(1));
Will Brockman2b6959e2020-01-22 09:59:50 -05001268 }
1269
1270 @Test
Will Brockmancfd98302020-01-29 15:57:30 -05001271 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1272 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1273 Notification notification = new Notification.Builder(mContext,
1274 mTestNotificationChannel.getId())
1275 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1276 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1277 waitForIdle();
1278 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1279 waitForIdle();
1280 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1281 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001282 assertEquals(3, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001283
Will Brockmancfd98302020-01-29 15:57:30 -05001284 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001285 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001286 mNotificationRecordLogger.event(0));
1287 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman4f0f9d22020-02-23 21:18:11 -05001288 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001289
Will Brockmancfd98302020-01-29 15:57:30 -05001290 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001291 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
Will Brockman9918db92020-03-06 16:48:39 -05001292 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001293 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001294
1295 assertEquals(
1296 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001297 mNotificationRecordLogger.event(2));
1298 assertTrue(mNotificationRecordLogger.get(2).wasLogged);
Will Brockmancfd98302020-01-29 15:57:30 -05001299 // New instance ID because notification was canceled before re-post
Will Brockman4f0f9d22020-02-23 21:18:11 -05001300 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001301 }
1302
1303 @Test
1304 public void testCancelNonexistentNotification() throws Exception {
1305 mBinderService.cancelNotificationWithTag(PKG, PKG,
1306 "testCancelNonexistentNotification", 0, 0);
1307 waitForIdle();
1308 // The notification record logger doesn't even get called when a nonexistent notification
1309 // is cancelled, because that happens very frequently and is not interesting.
Will Brockman9918db92020-03-06 16:48:39 -05001310 assertEquals(0, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001311 }
1312
1313 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001314 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001315 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1316 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001317 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001318 mBinderService.cancelNotificationWithTag(PKG, PKG,
1319 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001320 waitForIdle();
1321 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001322 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001323 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001324 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001325 }
1326
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001327 @Test
Evan Lairdd04af512020-01-09 11:18:09 -05001328 public void testPostCancelPostNotifiesListeners() throws Exception {
1329 // WHEN a notification is posted
1330 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1331 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1332 sbn.getNotification(), sbn.getUserId());
1333 // THEN it is canceled
1334 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1335 // THEN it is posted again (before the cancel has a chance to finish)
1336 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1337 sbn.getNotification(), sbn.getUserId());
1338 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
1339 waitForIdle();
1340
1341 // The final enqueue made it to the listener instead of being canceled
1342 StatusBarNotification[] notifs =
1343 mBinderService.getActiveNotifications(PKG);
1344 assertEquals(1, notifs.length);
1345 assertEquals(1, mService.getNotificationRecordCount());
1346 }
1347
1348 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001349 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001350 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1351 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001352 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001353 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001354 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1355 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001356 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001357 mBinderService.cancelNotificationWithTag(PKG, PKG,
1358 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001359 waitForIdle();
1360 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001361 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001362 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001363 assertEquals(0, mService.getNotificationRecordCount());
1364 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1365 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1366 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001367 }
1368
1369 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001370 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001371 NotificationRecord r = generateNotificationRecord(null);
Julia Reynolds24edc002020-01-29 16:35:32 -05001372 final StatusBarNotification sbn = r.getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001373 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1374 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001375 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001376 mBinderService.cancelNotificationsFromListener(null, null);
1377 waitForIdle();
1378 StatusBarNotification[] notifs =
1379 mBinderService.getActiveNotifications(sbn.getPackageName());
1380 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001381 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001382 }
1383
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001384 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001385 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001386 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001387 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1388 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001389 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001390 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001391 waitForIdle();
1392 StatusBarNotification[] notifs =
1393 mBinderService.getActiveNotifications(sbn.getPackageName());
1394 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001395 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001396 }
1397
1398 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001399 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1400 throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001401 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001402 sbn.getNotification().flags =
1403 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1404 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1405 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1406 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1407 waitForIdle();
1408 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1409 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1410 }
1411
1412 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001413 public void testUserInitiatedClearAll_noLeak() throws Exception {
1414 final NotificationRecord n = generateNotificationRecord(
1415 mTestNotificationChannel, 1, "group", true);
1416
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001417 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1418 "testUserInitiatedClearAll_noLeak",
Julia Reynolds24edc002020-01-29 16:35:32 -05001419 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001420 waitForIdle();
1421
Julia Reynolds503ed942017-10-04 16:04:56 -04001422 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001423 n.getUserId());
1424 waitForIdle();
1425 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001426 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
Julia Reynolds080361e2017-07-13 11:23:12 -04001427 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001428 assertEquals(0, mService.getNotificationRecordCount());
1429 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1430 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1431 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001432 }
1433
1434 @Test
1435 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1436 final NotificationRecord parent = generateNotificationRecord(
1437 mTestNotificationChannel, 1, "group1", true);
1438 final NotificationRecord child = generateNotificationRecord(
1439 mTestNotificationChannel, 2, "group1", false);
1440
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001441 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1442 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001443 parent.getSbn().getId(), parent.getSbn().getNotification(),
1444 parent.getSbn().getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001445 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1446 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001447 child.getSbn().getId(), child.getSbn().getNotification(),
1448 child.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001449 waitForIdle();
1450
Julia Reynolds24edc002020-01-29 16:35:32 -05001451 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001452 waitForIdle();
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
Julia Reynolds0839c022017-06-15 15:24:01 -04001457 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001458 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds0839c022017-06-15 15:24:01 -04001459 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001460 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1461 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001462 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1463 }
1464 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1465 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001466
Julia Reynolds503ed942017-10-04 16:04:56 -04001467 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001468 }
1469
1470 @Test
1471 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1472 final NotificationRecord parent = generateNotificationRecord(
1473 mTestNotificationChannel, 1, "group1", true);
1474 final NotificationRecord parentAsChild = generateNotificationRecord(
1475 mTestNotificationChannel, 1, "group1", false);
1476 final NotificationRecord child = generateNotificationRecord(
1477 mTestNotificationChannel, 2, "group1", false);
1478
1479 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001480 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1481 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001482 parent.getSbn().getId(), parent.getSbn().getNotification(),
1483 parent.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001484 waitForIdle();
1485
1486 // enqueue the child several times
1487 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001488 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1489 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001490 child.getSbn().getId(), child.getSbn().getNotification(),
1491 child.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001492 }
1493 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001494 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1495 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001496 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
1497 parentAsChild.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001498 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001499
Julia Reynolds503ed942017-10-04 16:04:56 -04001500 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001501 }
1502
1503 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001504 public void testAutobundledSummary_notificationAdded() {
1505 NotificationRecord summary =
1506 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1507 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1508 mService.addNotification(summary);
1509 mService.mSummaryByGroupKey.put("pkg", summary);
1510 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1511 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001512 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001513
Julia Reynolds24edc002020-01-29 16:35:32 -05001514 assertTrue(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001515 }
1516
1517 @Test
1518 public void testAutobundledSummary_notificationRemoved() {
1519 NotificationRecord summary =
1520 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1521 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1522 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1523 mService.addNotification(summary);
1524 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1525 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1526 mService.mSummaryByGroupKey.put("pkg", summary);
1527
Mady Mellor6d775f82019-11-12 16:12:19 -08001528 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001529
Julia Reynolds24edc002020-01-29 16:35:32 -05001530 assertFalse(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001531 }
1532
1533 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001534 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001535 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001536 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001537 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1538 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001539 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001540 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001541 waitForIdle();
1542 StatusBarNotification[] notifs =
1543 mBinderService.getActiveNotifications(sbn.getPackageName());
1544 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001545 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001546 }
1547
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001548 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001549 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001550 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001551 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001552 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1553 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001554 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001555 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1556 waitForIdle();
1557 StatusBarNotification[] notifs =
1558 mBinderService.getActiveNotifications(sbn.getPackageName());
1559 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001560 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001561 }
1562
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001563 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001564 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001565 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001566 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1567 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001568 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001569 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1570 waitForIdle();
1571 StatusBarNotification[] notifs =
1572 mBinderService.getActiveNotifications(sbn.getPackageName());
1573 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001574 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001575 }
1576
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001577 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001578 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001579 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001580 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1581 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001582 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001583 // Null pkg is how we signal a user switch.
1584 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1585 waitForIdle();
1586 StatusBarNotification[] notifs =
1587 mBinderService.getActiveNotifications(sbn.getPackageName());
1588 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001589 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001590 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001591
1592 @Test
Beverly40239d92017-07-07 10:20:41 -04001593 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001594 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Beverly40239d92017-07-07 10:20:41 -04001595 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001596 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1597 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001598 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1599 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1600 waitForIdle();
1601 StatusBarNotification[] notifs =
1602 mBinderService.getActiveNotifications(sbn.getPackageName());
1603 assertEquals(0, notifs.length);
1604 }
1605
1606 @Test
1607 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1608 final NotificationRecord notif = generateNotificationRecord(
1609 mTestNotificationChannel, 1, "group", true);
1610 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001611 mService.addNotification(notif);
1612 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001613 notif.getUserId(), 0, null);
1614 waitForIdle();
1615 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001616 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001617 assertEquals(0, notifs.length);
1618 }
1619
1620 @Test
1621 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1622 final NotificationRecord notif = generateNotificationRecord(
1623 mTestNotificationChannel, 1, "group", true);
1624 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001625 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001626
Julia Reynolds503ed942017-10-04 16:04:56 -04001627 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001628 notif.getUserId());
1629 waitForIdle();
1630 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001631 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001632 assertEquals(1, notifs.length);
1633 }
1634
1635 @Test
1636 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1637 final NotificationRecord parent = generateNotificationRecord(
1638 mTestNotificationChannel, 1, "group", true);
1639 final NotificationRecord child = generateNotificationRecord(
1640 mTestNotificationChannel, 2, "group", false);
1641 final NotificationRecord child2 = generateNotificationRecord(
1642 mTestNotificationChannel, 3, "group", false);
1643 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1644 final NotificationRecord newGroup = generateNotificationRecord(
1645 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001646 mService.addNotification(parent);
1647 mService.addNotification(child);
1648 mService.addNotification(child2);
1649 mService.addNotification(newGroup);
1650 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001651 waitForIdle();
1652 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001653 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001654 assertEquals(1, notifs.length);
1655 }
1656
1657 @Test
1658 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1659 final NotificationRecord parent = generateNotificationRecord(
1660 mTestNotificationChannel, 1, "group", true);
1661 final NotificationRecord child = generateNotificationRecord(
1662 mTestNotificationChannel, 2, "group", false);
1663 final NotificationRecord child2 = generateNotificationRecord(
1664 mTestNotificationChannel, 3, "group", false);
1665 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1666 final NotificationRecord newGroup = generateNotificationRecord(
1667 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001668 mService.addNotification(parent);
1669 mService.addNotification(child);
1670 mService.addNotification(child2);
1671 mService.addNotification(newGroup);
1672 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001673 parent.getUserId());
1674 waitForIdle();
1675 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001676 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001677 assertEquals(1, notifs.length);
1678 }
1679
1680 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001681 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001682 Notification n =
1683 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1684 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1685 .build();
1686 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
1687 n, new UserHandle(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001688 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001689 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001690 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001691 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1692 sbn.getUserId());
1693 waitForIdle();
1694 StatusBarNotification[] notifs =
1695 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001696 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001697 }
1698
1699 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001700 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001701 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001702 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001703 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001704 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001705 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1706 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001707 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001708 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001709 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1710 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001711 waitForIdle();
1712 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001713 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001714 }
1715
1716 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001717 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1718 throws Exception {
1719 final NotificationRecord parent = generateNotificationRecord(
1720 mTestNotificationChannel, 1, "group", true);
1721 final NotificationRecord child = generateNotificationRecord(
1722 mTestNotificationChannel, 2, "group", false);
1723 final NotificationRecord child2 = generateNotificationRecord(
1724 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001725 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001726 final NotificationRecord newGroup = generateNotificationRecord(
1727 mTestNotificationChannel, 4, "group2", false);
1728 mService.addNotification(parent);
1729 mService.addNotification(child);
1730 mService.addNotification(child2);
1731 mService.addNotification(newGroup);
1732 mService.getBinderService().cancelNotificationsFromListener(null, null);
1733 waitForIdle();
1734 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001735 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001736 assertEquals(0, notifs.length);
1737 }
1738
1739 @Test
1740 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1741 throws Exception {
1742 final NotificationRecord parent = generateNotificationRecord(
1743 mTestNotificationChannel, 1, "group", true);
1744 final NotificationRecord child = generateNotificationRecord(
1745 mTestNotificationChannel, 2, "group", false);
1746 final NotificationRecord child2 = generateNotificationRecord(
1747 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001748 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001749 final NotificationRecord newGroup = generateNotificationRecord(
1750 mTestNotificationChannel, 4, "group2", false);
1751 mService.addNotification(parent);
1752 mService.addNotification(child);
1753 mService.addNotification(child2);
1754 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001755 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1756 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001757 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1758 waitForIdle();
1759 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001760 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001761 assertEquals(1, notifs.length);
1762 }
1763
1764 @Test
1765 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1766 final NotificationRecord parent = generateNotificationRecord(
1767 mTestNotificationChannel, 1, "group", true);
1768 final NotificationRecord child = generateNotificationRecord(
1769 mTestNotificationChannel, 2, "group", false);
1770 final NotificationRecord child2 = generateNotificationRecord(
1771 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001772 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001773 final NotificationRecord newGroup = generateNotificationRecord(
1774 mTestNotificationChannel, 4, "group2", false);
1775 mService.addNotification(parent);
1776 mService.addNotification(child);
1777 mService.addNotification(child2);
1778 mService.addNotification(newGroup);
1779 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1780 parent.getUserId());
1781 waitForIdle();
1782 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001783 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001784 assertEquals(0, notifs.length);
1785 }
1786
1787 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001788 public void testFindGroupNotificationsLocked() throws Exception {
1789 // make sure the same notification can be found in both lists and returned
1790 final NotificationRecord group1 = generateNotificationRecord(
1791 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001792 mService.addEnqueuedNotification(group1);
1793 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001794
1795 // should not be returned
1796 final NotificationRecord group2 = generateNotificationRecord(
1797 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001798 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001799 group2.getSbn().getId(), group2.getSbn().getNotification(),
1800 group2.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001801 waitForIdle();
1802
1803 // should not be returned
1804 final NotificationRecord nonGroup = generateNotificationRecord(
1805 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001806 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001807 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
1808 nonGroup.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001809 waitForIdle();
1810
1811 // same group, child, should be returned
1812 final NotificationRecord group1Child = generateNotificationRecord(
1813 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001814 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001815 group1Child.getSbn().getId(),
1816 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001817 waitForIdle();
1818
1819 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001820 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynolds24edc002020-01-29 16:35:32 -05001821 group1.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001822 assertEquals(3, inGroup1.size());
1823 for (NotificationRecord record : inGroup1) {
1824 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
Julia Reynolds24edc002020-01-29 16:35:32 -05001825 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001826 }
1827 }
1828
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001829 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001830 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1831 final NotificationRecord notif = generateNotificationRecord(
1832 mTestNotificationChannel, 1, "group", true);
1833 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1834 mService.addNotification(notif);
1835 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1836 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1837 waitForIdle();
1838 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001839 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001840 assertEquals(0, notifs.length);
1841 }
1842
1843 @Test
1844 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1845 throws Exception {
1846 final NotificationRecord parent = generateNotificationRecord(
1847 mTestNotificationChannel, 1, "group", true);
1848 final NotificationRecord child = generateNotificationRecord(
1849 mTestNotificationChannel, 2, "group", false);
1850 final NotificationRecord child2 = generateNotificationRecord(
1851 mTestNotificationChannel, 3, "group", false);
1852 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1853 final NotificationRecord newGroup = generateNotificationRecord(
1854 mTestNotificationChannel, 4, "group2", false);
1855 mService.addNotification(parent);
1856 mService.addNotification(child);
1857 mService.addNotification(child2);
1858 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001859 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1860 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001861 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1862 waitForIdle();
1863 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001864 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001865 assertEquals(0, notifs.length);
1866 }
1867
1868 @Test
1869 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001870 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds40f00d72017-12-12 10:47:32 -05001871 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001872 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1873 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001874 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1875 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1876 waitForIdle();
1877 StatusBarNotification[] notifs =
1878 mBinderService.getActiveNotifications(sbn.getPackageName());
1879 assertEquals(0, notifs.length);
1880 }
1881
1882 @Test
1883 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1884 final NotificationRecord notif = generateNotificationRecord(
1885 mTestNotificationChannel, 1, "group", true);
1886 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1887 mService.addNotification(notif);
1888 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1889 notif.getUserId(), 0, null);
1890 waitForIdle();
1891 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001892 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001893 assertEquals(0, notifs.length);
1894 }
1895
1896 @Test
1897 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1898 final NotificationRecord notif = generateNotificationRecord(
1899 mTestNotificationChannel, 1, "group", true);
1900 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1901 mService.addNotification(notif);
1902
1903 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1904 notif.getUserId());
1905 waitForIdle();
1906 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001907 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001908 assertEquals(1, notifs.length);
1909 }
1910
1911 @Test
1912 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1913 final NotificationRecord parent = generateNotificationRecord(
1914 mTestNotificationChannel, 1, "group", true);
1915 final NotificationRecord child = generateNotificationRecord(
1916 mTestNotificationChannel, 2, "group", false);
1917 final NotificationRecord child2 = generateNotificationRecord(
1918 mTestNotificationChannel, 3, "group", false);
1919 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1920 final NotificationRecord newGroup = generateNotificationRecord(
1921 mTestNotificationChannel, 4, "group2", false);
1922 mService.addNotification(parent);
1923 mService.addNotification(child);
1924 mService.addNotification(child2);
1925 mService.addNotification(newGroup);
1926 mService.getBinderService().cancelNotificationsFromListener(null, null);
1927 waitForIdle();
1928 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001929 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001930 assertEquals(1, notifs.length);
1931 }
1932
1933 @Test
1934 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1935 throws Exception {
1936 final NotificationRecord parent = generateNotificationRecord(
1937 mTestNotificationChannel, 1, "group", true);
1938 final NotificationRecord child = generateNotificationRecord(
1939 mTestNotificationChannel, 2, "group", false);
1940 final NotificationRecord child2 = generateNotificationRecord(
1941 mTestNotificationChannel, 3, "group", false);
1942 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1943 final NotificationRecord newGroup = generateNotificationRecord(
1944 mTestNotificationChannel, 4, "group2", false);
1945 mService.addNotification(parent);
1946 mService.addNotification(child);
1947 mService.addNotification(child2);
1948 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001949 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1950 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001951 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1952 waitForIdle();
1953 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001954 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001955 assertEquals(0, notifs.length);
1956 }
1957
1958 @Test
1959 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1960 final NotificationRecord parent = generateNotificationRecord(
1961 mTestNotificationChannel, 1, "group", true);
1962 final NotificationRecord child = generateNotificationRecord(
1963 mTestNotificationChannel, 2, "group", false);
1964 final NotificationRecord child2 = generateNotificationRecord(
1965 mTestNotificationChannel, 3, "group", false);
1966 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1967 final NotificationRecord newGroup = generateNotificationRecord(
1968 mTestNotificationChannel, 4, "group2", false);
1969 mService.addNotification(parent);
1970 mService.addNotification(child);
1971 mService.addNotification(child2);
1972 mService.addNotification(newGroup);
1973 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1974 parent.getUserId());
1975 waitForIdle();
1976 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001977 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001978 assertEquals(1, notifs.length);
1979 }
1980
1981 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001982 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001983 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001984 mService.setPreferencesHelper(mPreferencesHelper);
1985 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001986 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001987 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001988
Julia Reynoldsbad42972017-04-25 13:52:49 -04001989 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001990 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001991 generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05001992 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
1993 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001994 }
1995
1996 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001997 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001998 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001999 mService.setPreferencesHelper(mPreferencesHelper);
2000 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002001 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05002002 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002003
Julia Reynoldsbad42972017-04-25 13:52:49 -04002004 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002005 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
2006 0, generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002007 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
Julia Reynolds0f767342019-12-18 09:11:55 -05002008 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002009 anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002010 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002011
2012 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002013 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002014 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002015
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002016 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002017 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2018 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2019
2020 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2021 captor.getValue().getAction());
2022 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002023 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2024 }
2025
2026 @Test
2027 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
2028 mService.setPreferencesHelper(mPreferencesHelper);
2029
2030 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
2031 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002032 }
2033
2034 @Test
2035 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002036 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002037
2038 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
2039 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2040 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2041
2042 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2043 captor.getValue().getAction());
2044 assertEquals(PKG, captor.getValue().getPackage());
2045 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2046 }
2047
2048 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002049 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002050 mService.setPreferencesHelper(mPreferencesHelper);
2051 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002052 eq(mTestNotificationChannel.getId()), anyBoolean()))
2053 .thenReturn(mTestNotificationChannel);
2054
2055 NotificationChannel updatedChannel =
2056 new NotificationChannel(mTestNotificationChannel.getId(),
2057 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
2058
2059 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
2060 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2061 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2062
2063 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2064 captor.getValue().getAction());
2065 assertEquals(PKG, captor.getValue().getPackage());
2066 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002067 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002068 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2069 }
2070
2071 @Test
2072 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
2073 NotificationChannel existingChannel =
2074 new NotificationChannel(mTestNotificationChannel.getId(),
2075 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002076 mService.setPreferencesHelper(mPreferencesHelper);
2077 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002078 eq(mTestNotificationChannel.getId()), anyBoolean()))
2079 .thenReturn(existingChannel);
2080
2081 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2082 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2083 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2084
2085 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2086 captor.getValue().getAction());
2087 assertEquals(PKG, captor.getValue().getPackage());
2088 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002089 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002090 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2091 }
2092
2093 @Test
2094 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
2095 NotificationChannel existingChannel =
2096 new NotificationChannel(mTestNotificationChannel.getId(),
2097 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002098 mService.setPreferencesHelper(mPreferencesHelper);
2099 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002100 eq(mTestNotificationChannel.getId()), anyBoolean()))
2101 .thenReturn(existingChannel);
2102
2103 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2104 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2105 }
2106
2107 @Test
2108 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
2109 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002110 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002111 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2112 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002113 .thenReturn(existing);
2114
2115 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
2116 updated.setBlocked(true);
2117
2118 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
2119 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2120 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2121
2122 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2123 captor.getValue().getAction());
2124 assertEquals(PKG, captor.getValue().getPackage());
2125 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002126 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002127 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2128 }
2129
2130 @Test
2131 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
2132 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2133 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002134 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002135 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2136 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002137 .thenReturn(existing);
2138
2139 mBinderService.updateNotificationChannelGroupForPackage(
2140 PKG, 0, new NotificationChannelGroup("id", "name"));
2141 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2142 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2143
2144 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2145 captor.getValue().getAction());
2146 assertEquals(PKG, captor.getValue().getPackage());
2147 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002148 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002149 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2150 }
2151
2152 @Test
2153 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
2154 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002155 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002156 when(mPreferencesHelper.getNotificationChannelGroup(
2157 eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002158 .thenReturn(existing);
2159
2160 mBinderService.updateNotificationChannelGroupForPackage(
2161 PKG, 0, new NotificationChannelGroup("id", "new name"));
2162 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2163 }
2164
2165 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002166 public void testCreateChannelNotifyListener() throws Exception {
2167 List<String> associations = new ArrayList<>();
2168 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002169 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002170 mService.setPreferencesHelper(mPreferencesHelper);
2171 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002172 eq(mTestNotificationChannel.getId()), anyBoolean()))
2173 .thenReturn(mTestNotificationChannel);
2174 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002175 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002176 eq(channel2.getId()), anyBoolean()))
2177 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002178 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
2179 eq(channel2), anyBoolean(), anyBoolean()))
2180 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002181
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002182 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002183 mBinderService.createNotificationChannels(PKG,
2184 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002185 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002186 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002187 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002188 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002189 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002190 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2191 }
2192
2193 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002194 public void testCreateChannelGroupNotifyListener() throws Exception {
2195 List<String> associations = new ArrayList<>();
2196 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002197 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002198 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002199 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
2200 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
2201
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002202 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002203 mBinderService.createNotificationChannelGroups(PKG,
2204 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002205 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002206 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002207 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002208 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002209 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002210 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2211 }
2212
2213 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002214 public void testUpdateChannelNotifyListener() throws Exception {
2215 List<String> associations = new ArrayList<>();
2216 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002217 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002218 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002219 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002220 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002221 eq(mTestNotificationChannel.getId()), anyBoolean()))
2222 .thenReturn(mTestNotificationChannel);
2223
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002224 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002225 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002226 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002227 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002228 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2229 }
2230
2231 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002232 public void testDeleteChannelNotifyListener() throws Exception {
2233 List<String> associations = new ArrayList<>();
2234 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002235 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002236 mService.setPreferencesHelper(mPreferencesHelper);
2237 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002238 eq(mTestNotificationChannel.getId()), anyBoolean()))
2239 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002240 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002241 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002242 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002243 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002244 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2245 }
2246
2247 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002248 public void testDeleteChannelGroupNotifyListener() throws Exception {
2249 List<String> associations = new ArrayList<>();
2250 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002251 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002252 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002253 mService.setPreferencesHelper(mPreferencesHelper);
2254 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002255 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002256 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002257 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002258 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002259 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002260 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2261 }
2262
2263 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002264 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002265 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002266 List<String> associations = new ArrayList<>();
2267 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002268 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002269 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002270 eq(mTestNotificationChannel.getId()), anyBoolean()))
2271 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002272
2273 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002274 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002275
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002276 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002277 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002278
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002279 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002280 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002281 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2282 }
2283
2284 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002285 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002286 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002287 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002288 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002289
2290 try {
2291 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002292 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002293 fail("listeners that don't have a companion device shouldn't be able to call this");
2294 } catch (SecurityException e) {
2295 // pass
2296 }
2297
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002298 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002299 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002300
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002301 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002302 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2303 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2304 }
2305
2306 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002307 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002308 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002309 List<String> associations = new ArrayList<>();
2310 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002311 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002312 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002313 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002314 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002315 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002316
2317 try {
2318 mBinderService.updateNotificationChannelFromPrivilegedListener(
2319 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2320 fail("incorrectly allowed a change to a user listener cannot see");
2321 } catch (SecurityException e) {
2322 // pass
2323 }
2324
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002325 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002326 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002327
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002328 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002329 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002330 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2331 }
2332
2333 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002334 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002335 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002336 List<String> associations = new ArrayList<>();
2337 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002338 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002339
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002340 mBinderService.getNotificationChannelsFromPrivilegedListener(
2341 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002342
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002343 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002344 anyString(), anyInt(), anyBoolean());
2345 }
2346
2347 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002348 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002349 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002350 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002351 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002352
2353 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002354 mBinderService.getNotificationChannelsFromPrivilegedListener(
2355 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002356 fail("listeners that don't have a companion device shouldn't be able to call this");
2357 } catch (SecurityException e) {
2358 // pass
2359 }
2360
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002361 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002362 anyString(), anyInt(), anyBoolean());
2363 }
2364
2365 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002366 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2367 throws Exception {
2368 mService.setPreferencesHelper(mPreferencesHelper);
2369 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2370 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2371
2372 mBinderService.getNotificationChannelsFromPrivilegedListener(
2373 null, PKG, Process.myUserHandle());
2374
2375 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2376 anyString(), anyInt(), anyBoolean());
2377 }
2378
2379 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002380 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2381 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002382 mService.setPreferencesHelper(mPreferencesHelper);
2383 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2384 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2385
2386 try {
2387 mBinderService.getNotificationChannelsFromPrivilegedListener(
2388 null, PKG, Process.myUserHandle());
2389 fail("listeners that don't have a companion device shouldn't be able to call this");
2390 } catch (SecurityException e) {
2391 // pass
2392 }
2393
2394 verify(mPreferencesHelper, never()).getNotificationChannels(
2395 anyString(), anyInt(), anyBoolean());
2396 }
2397
2398 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002399 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002400 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002401 List<String> associations = new ArrayList<>();
2402 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002403 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002404 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2405 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002406 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002407
2408 try {
2409 mBinderService.getNotificationChannelsFromPrivilegedListener(
2410 null, PKG, Process.myUserHandle());
2411 fail("listener getting channels from a user they cannot see");
2412 } catch (SecurityException e) {
2413 // pass
2414 }
2415
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002416 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002417 anyString(), anyInt(), anyBoolean());
2418 }
2419
2420 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002421 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002422 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002423 List<String> associations = new ArrayList<>();
2424 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002425 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002426
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002427 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2428 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002429
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002430 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002431 }
2432
2433 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002434 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002435 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002436 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002437 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002438
2439 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002440 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2441 null, PKG, Process.myUserHandle());
2442 fail("listeners that don't have a companion device shouldn't be able to call this");
2443 } catch (SecurityException e) {
2444 // pass
2445 }
2446
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002447 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002448 }
2449
2450 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002451 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002452 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002453 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002454 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002455 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2456 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002457 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002458 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002459 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2460 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002461 fail("listeners that don't have a companion device shouldn't be able to call this");
2462 } catch (SecurityException e) {
2463 // pass
2464 }
2465
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002466 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002467 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002468
2469 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002470 public void testHasCompanionDevice_failure() throws Exception {
2471 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2472 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002473 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002474 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002475
2476 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002477 public void testHasCompanionDevice_noService() {
Will Brockmancfd98302020-01-29 15:57:30 -05002478 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
2479 mNotificationInstanceIdSequence);
Julia Reynolds727a7282017-04-13 10:54:01 -04002480
Julia Reynolds503ed942017-10-04 16:04:56 -04002481 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002482 }
2483
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002484 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002485 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2486 final NotificationRecord notification = generateNotificationRecord(
2487 mTestNotificationChannel, 1, null, true);
2488 mService.addNotification(notification);
2489 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2490
2491 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2492 mService.new SnoozeNotificationRunnable(
2493 notification.getKey(), 100, null);
2494 snoozeNotificationRunnable.run();
2495 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2496 mService.new SnoozeNotificationRunnable(
2497 notification.getKey(), 100, null);
2498 snoozeNotificationRunnable.run();
2499
2500 // snooze twice
2501 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2502 }
2503
2504 @Test
2505 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2506 final NotificationRecord notification = generateNotificationRecord(
2507 mTestNotificationChannel, 1, "group", true);
2508 mService.addNotification(notification);
2509 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2510
2511 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2512 mService.new SnoozeNotificationRunnable(
2513 notification.getKey(), 100, null);
2514 snoozeNotificationRunnable.run();
2515 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2516 mService.new SnoozeNotificationRunnable(
2517 notification.getKey(), 100, null);
2518 snoozeNotificationRunnable.run();
2519
2520 // snooze twice
2521 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2522 }
2523
2524 @Test
2525 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2526 final NotificationRecord notification = generateNotificationRecord(
2527 mTestNotificationChannel, 1, "group", true);
2528 final NotificationRecord notification2 = generateNotificationRecord(
2529 mTestNotificationChannel, 2, "group", true);
2530 mService.addNotification(notification);
2531 mService.addNotification(notification2);
2532 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2533 when(mSnoozeHelper.getNotifications(
2534 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2535
2536 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2537 mService.new SnoozeNotificationRunnable(
2538 notification.getKey(), 100, null);
2539 snoozeNotificationRunnable.run();
2540 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2541 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2542 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2543 mService.new SnoozeNotificationRunnable(
2544 notification.getKey(), 100, null);
2545 snoozeNotificationRunnable.run();
2546
2547 // snooze twice
2548 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2549 }
2550
2551 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002552 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2553 final NotificationRecord nonGrouped = generateNotificationRecord(
2554 mTestNotificationChannel, 1, null, false);
2555 final NotificationRecord grouped = generateNotificationRecord(
2556 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002557 mService.addNotification(grouped);
2558 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002559
2560 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002561 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002562 nonGrouped.getKey(), 100, null);
2563 snoozeNotificationRunnable.run();
2564
2565 // only snooze the one notification
2566 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002567 assertTrue(nonGrouped.getStats().hasSnoozed());
Will Brockman9918db92020-03-06 16:48:39 -05002568
2569 assertEquals(2, mNotificationRecordLogger.numCalls());
2570 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2571 mNotificationRecordLogger.event(0));
2572 assertEquals(
2573 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2574 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002575 }
2576
2577 @Test
2578 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2579 final NotificationRecord parent = generateNotificationRecord(
2580 mTestNotificationChannel, 1, "group", true);
2581 final NotificationRecord child = generateNotificationRecord(
2582 mTestNotificationChannel, 2, "group", false);
2583 final NotificationRecord child2 = generateNotificationRecord(
2584 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002585 mService.addNotification(parent);
2586 mService.addNotification(child);
2587 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002588
2589 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002590 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002591 parent.getKey(), 100, null);
2592 snoozeNotificationRunnable.run();
2593
2594 // snooze parent and children
2595 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2596 }
2597
2598 @Test
2599 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2600 final NotificationRecord parent = generateNotificationRecord(
2601 mTestNotificationChannel, 1, "group", true);
2602 final NotificationRecord child = generateNotificationRecord(
2603 mTestNotificationChannel, 2, "group", false);
2604 final NotificationRecord child2 = generateNotificationRecord(
2605 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002606 mService.addNotification(parent);
2607 mService.addNotification(child);
2608 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002609
2610 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002611 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002612 child2.getKey(), 100, null);
2613 snoozeNotificationRunnable.run();
2614
2615 // only snooze the one child
2616 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002617
2618 assertEquals(2, mNotificationRecordLogger.numCalls());
2619 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2620 mNotificationRecordLogger.event(0));
2621 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
2622 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002623 }
2624
2625 @Test
2626 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2627 final NotificationRecord parent = generateNotificationRecord(
2628 mTestNotificationChannel, 1, "group", true);
Julia Reynolds24edc002020-01-29 16:35:32 -05002629 assertTrue(parent.getSbn().getNotification().isGroupSummary());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002630 final NotificationRecord child = generateNotificationRecord(
2631 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002632 mService.addNotification(parent);
2633 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002634
2635 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002636 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002637 child.getKey(), 100, null);
2638 snoozeNotificationRunnable.run();
2639
2640 // snooze child and summary
2641 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002642
2643 assertEquals(4, mNotificationRecordLogger.numCalls());
2644 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2645 mNotificationRecordLogger.event(0));
2646 assertEquals(
2647 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2648 mNotificationRecordLogger.event(1));
2649 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2650 mNotificationRecordLogger.event(2));
2651 assertEquals(
2652 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2653 mNotificationRecordLogger.event(3));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002654 }
2655
2656 @Test
2657 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2658 final NotificationRecord child = generateNotificationRecord(
2659 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002660 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002661
2662 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002663 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002664 child.getKey(), 100, null);
2665 snoozeNotificationRunnable.run();
2666
2667 // snooze child only
2668 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002669
2670 assertEquals(2, mNotificationRecordLogger.numCalls());
2671 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2672 mNotificationRecordLogger.event(0));
2673 assertEquals(
2674 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2675 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002676 }
2677
2678 @Test
2679 public void testPostGroupChild_unsnoozeParent() throws Exception {
2680 final NotificationRecord child = generateNotificationRecord(
2681 mTestNotificationChannel, 2, "group", false);
2682
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002683 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002684 child.getSbn().getId(), child.getSbn().getNotification(),
2685 child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002686 waitForIdle();
2687
2688 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2689 anyString(), anyInt(), eq(child.getGroupKey()));
2690 }
2691
2692 @Test
2693 public void testPostNonGroup_noUnsnoozing() throws Exception {
2694 final NotificationRecord record = generateNotificationRecord(
2695 mTestNotificationChannel, 2, null, false);
2696
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002697 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002698 record.getSbn().getId(), record.getSbn().getNotification(),
2699 record.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002700 waitForIdle();
2701
2702 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2703 }
2704
2705 @Test
2706 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2707 final NotificationRecord parent = generateNotificationRecord(
2708 mTestNotificationChannel, 2, "group", true);
2709
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002710 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002711 parent.getSbn().getId(), parent.getSbn().getNotification(),
2712 parent.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002713 waitForIdle();
2714
2715 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2716 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002717
2718 @Test
Julia Reynolds0d073782020-02-13 16:07:52 -05002719 public void testSystemNotificationListenerCanUnsnooze() throws Exception {
2720 final NotificationRecord nr = generateNotificationRecord(
2721 mTestNotificationChannel, 2, "group", false);
2722
2723 mBinderService.enqueueNotificationWithTag(PKG, PKG,
2724 "testSystemNotificationListenerCanUnsnooze",
2725 nr.getSbn().getId(), nr.getSbn().getNotification(),
2726 nr.getSbn().getUserId());
2727 waitForIdle();
2728 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2729 mService.new SnoozeNotificationRunnable(
2730 nr.getKey(), 100, null);
2731 snoozeNotificationRunnable.run();
2732
2733 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
2734 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
2735 listener.isSystem = true;
2736 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
2737
2738 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
2739 waitForIdle();
2740 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
2741 assertEquals(1, notifs.length);
2742 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
2743 }
2744
2745 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002746 public void testSetListenerAccessForUser() throws Exception {
2747 UserHandle user = UserHandle.of(10);
2748 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002749 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2750
Julia Reynolds92febc32017-10-26 11:30:31 -04002751
2752 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2753 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2754 c.flattenToString(), user.getIdentifier(), true, true);
2755 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2756 c.flattenToString(), user.getIdentifier(), false, true);
2757 verify(mAssistants, never()).setPackageOrComponentEnabled(
2758 any(), anyInt(), anyBoolean(), anyBoolean());
2759 }
2760
2761 @Test
2762 public void testSetAssistantAccessForUser() throws Exception {
2763 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002764 List<UserInfo> uis = new ArrayList<>();
2765 UserInfo ui = new UserInfo();
2766 ui.id = 10;
2767 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002768 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002769 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2770
2771 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002772
2773 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2774 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2775 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002776 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002777 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2778 c.flattenToString(), user.getIdentifier(), false, true);
2779 verify(mListeners, never()).setPackageOrComponentEnabled(
2780 any(), anyInt(), anyBoolean(), anyBoolean());
2781 }
2782
2783 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002784 public void testGetAssistantAllowedForUser() throws Exception {
2785 UserHandle user = UserHandle.of(10);
2786 try {
2787 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2788 } catch (IllegalStateException e) {
2789 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2790 throw e;
2791 }
2792 }
2793 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2794 }
2795
2796 @Test
2797 public void testGetAssistantAllowed() throws Exception {
2798 try {
2799 mBinderService.getAllowedNotificationAssistant();
2800 } catch (IllegalStateException e) {
2801 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2802 throw e;
2803 }
2804 }
2805 verify(mAssistants, times(1)).getAllowedComponents(0);
2806 }
2807
2808 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002809 public void testSetDndAccessForUser() throws Exception {
2810 UserHandle user = UserHandle.of(10);
2811 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002812 mBinderService.setNotificationPolicyAccessGrantedForUser(
2813 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002814
2815 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2816 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2817 c.getPackageName(), user.getIdentifier(), true, true);
2818 verify(mAssistants, never()).setPackageOrComponentEnabled(
2819 any(), anyInt(), anyBoolean(), anyBoolean());
2820 verify(mListeners, never()).setPackageOrComponentEnabled(
2821 any(), anyInt(), anyBoolean(), anyBoolean());
2822 }
2823
2824 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002825 public void testSetListenerAccess() throws Exception {
2826 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002827 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002828
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002829 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002830 c.flattenToString(), 0, true, true);
2831 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2832 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002833 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002834 any(), anyInt(), anyBoolean(), anyBoolean());
2835 }
2836
2837 @Test
2838 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002839 List<UserInfo> uis = new ArrayList<>();
2840 UserInfo ui = new UserInfo();
2841 ui.id = 0;
2842 uis.add(ui);
2843 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002844 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002845
2846 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002847
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002848 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002849 c.flattenToString(), 0, true, true);
2850 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2851 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002852 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002853 any(), anyInt(), anyBoolean(), anyBoolean());
2854 }
2855
2856 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002857 public void testSetAssistantAccess_multiProfile() throws Exception {
2858 List<UserInfo> uis = new ArrayList<>();
2859 UserInfo ui = new UserInfo();
2860 ui.id = 0;
2861 uis.add(ui);
2862 UserInfo ui10 = new UserInfo();
2863 ui10.id = 10;
2864 uis.add(ui10);
2865 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2866 ComponentName c = ComponentName.unflattenFromString("package/Component");
2867
2868 mBinderService.setNotificationAssistantAccessGranted(c, true);
2869
2870 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2871 c.flattenToString(), 0, true, true);
2872 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2873 c.flattenToString(), 10, true, true);
2874 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2875 c.flattenToString(), 0, false, true);
2876 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2877 c.flattenToString(), 10, false, true);
2878 verify(mListeners, never()).setPackageOrComponentEnabled(
2879 any(), anyInt(), anyBoolean(), anyBoolean());
2880 }
2881
2882 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002883 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2884 ArrayList<ComponentName> componentList = new ArrayList<>();
2885 ComponentName c = ComponentName.unflattenFromString("package/Component");
2886 componentList.add(c);
2887 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002888 List<UserInfo> uis = new ArrayList<>();
2889 UserInfo ui = new UserInfo();
2890 ui.id = 0;
2891 uis.add(ui);
2892 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002893
Julia Reynolds4afe2642019-05-01 08:42:24 -04002894 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002895
2896 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2897 c.flattenToString(), 0, true, false);
2898 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2899 c.flattenToString(), 0, false, false);
2900 verify(mListeners, never()).setPackageOrComponentEnabled(
2901 any(), anyInt(), anyBoolean(), anyBoolean());
2902 }
2903
2904 @Test
2905 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002906 List<UserInfo> uis = new ArrayList<>();
2907 UserInfo ui = new UserInfo();
2908 ui.id = 10;
2909 uis.add(ui);
2910 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002911 ArrayList<ComponentName> componentList = new ArrayList<>();
2912 ComponentName c = ComponentName.unflattenFromString("package/Component");
2913 componentList.add(c);
2914 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002915 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002916
Julia Reynolds4afe2642019-05-01 08:42:24 -04002917 mBinderService.setNotificationAssistantAccessGrantedForUser(
2918 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002919
2920 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2921 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002922 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002923 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2924 c.flattenToString(), user.getIdentifier(), false, false);
2925 verify(mListeners, never()).setPackageOrComponentEnabled(
2926 any(), anyInt(), anyBoolean(), anyBoolean());
2927 }
2928
2929 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002930 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2931 throws Exception {
2932 List<UserInfo> uis = new ArrayList<>();
2933 UserInfo ui = new UserInfo();
2934 ui.id = 0;
2935 uis.add(ui);
2936 UserInfo ui10 = new UserInfo();
2937 ui10.id = 10;
2938 uis.add(ui10);
2939 UserHandle user = ui.getUserHandle();
2940 ArrayList<ComponentName> componentList = new ArrayList<>();
2941 ComponentName c = ComponentName.unflattenFromString("package/Component");
2942 componentList.add(c);
2943 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2944 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2945
2946 mBinderService.setNotificationAssistantAccessGrantedForUser(
2947 null, user.getIdentifier(), true);
2948
2949 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2950 c.flattenToString(), user.getIdentifier(), true, false);
2951 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2952 c.flattenToString(), ui10.id, true, false);
2953 verify(mAssistants).setUserSet(0, true);
2954 verify(mAssistants).setUserSet(10, true);
2955 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2956 c.flattenToString(), user.getIdentifier(), false, false);
2957 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2958 c.flattenToString(), ui10.id, false, false);
2959 verify(mListeners, never()).setPackageOrComponentEnabled(
2960 any(), anyInt(), anyBoolean(), anyBoolean());
2961 }
2962
2963 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002964 public void testSetDndAccess() throws Exception {
2965 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002966
2967 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002968
2969 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2970 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002971 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002972 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002973 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002974 any(), anyInt(), anyBoolean(), anyBoolean());
2975 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002976
2977 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002978 public void testSetListenerAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04002979 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2980 ComponentName c = ComponentName.unflattenFromString("package/Component");
2981 mBinderService.setNotificationListenerAccessGranted(c, true);
2982
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002983 verify(mListeners).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002984 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002985 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002986 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002987 verify(mAssistants).migrateToXml();
2988 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04002989 }
2990
2991 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002992 public void testSetAssistantAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04002993 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2994 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002995 List<UserInfo> uis = new ArrayList<>();
2996 UserInfo ui = new UserInfo();
2997 ui.id = 0;
2998 uis.add(ui);
2999 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3000
Julia Reynolds68263d12017-06-21 14:21:19 -04003001 mBinderService.setNotificationAssistantAccessGranted(c, true);
3002
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003003 verify(mListeners).migrateToXml();
3004 verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
3005 anyInt());
3006 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003007 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003008 verify(mAssistants).migrateToXml();
3009 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04003010 }
3011
3012 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003013 public void testSetDndAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003014 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3015 ComponentName c = ComponentName.unflattenFromString("package/Component");
3016 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3017
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003018 verify(mListeners).migrateToXml();
3019 verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
3020 anyInt());
3021 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003022 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003023 verify(mAssistants).migrateToXml();
3024 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynoldse1816412017-10-24 10:39:11 -04003025 }
3026
3027 @Test
3028 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3029 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3030 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3031 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003032
3033 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003034
3035 verify(mListeners, times(1)).setPackageOrComponentEnabled(
3036 c.flattenToString(), 0, true, true);
3037 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003038 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003039 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003040 any(), anyInt(), anyBoolean(), anyBoolean());
3041 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04003042
3043 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04003044 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3045 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3046 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3047 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003048 List<UserInfo> uis = new ArrayList<>();
3049 UserInfo ui = new UserInfo();
3050 ui.id = 0;
3051 uis.add(ui);
3052 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3053
3054 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003055
3056 verify(mListeners, never()).setPackageOrComponentEnabled(
3057 anyString(), anyInt(), anyBoolean(), anyBoolean());
3058 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3059 c.flattenToString(), 0, false, true);
3060 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3061 c.flattenToString(), 0, true, true);
3062 }
3063
3064 @Test
3065 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3066 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3067 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3068 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003069
3070 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003071
3072 verify(mListeners, never()).setPackageOrComponentEnabled(
3073 anyString(), anyInt(), anyBoolean(), anyBoolean());
3074 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3075 c.getPackageName(), 0, true, true);
3076 verify(mAssistants, never()).setPackageOrComponentEnabled(
3077 any(), anyInt(), anyBoolean(), anyBoolean());
3078 }
3079
3080 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04003081 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
3082 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003083 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003084 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003085 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003086 runnable.run();
3087 waitForIdle();
3088
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003089 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003090 }
3091
3092 @Test
3093 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
3094 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003095 NotificationRecord r =
3096 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003097 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003098
3099 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003100 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003101 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003102 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003103 runnable.run();
3104 waitForIdle();
3105
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003106 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003107 }
3108
3109 @Test
3110 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
3111 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04003112 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
3113 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003114 mService.addNotification(r);
3115 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003116
3117 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003118 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003119 runnable.run();
3120 waitForIdle();
3121
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003122 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003123 }
Beverly40239d92017-07-07 10:20:41 -04003124
Julia Reynolds4db59552017-06-30 13:34:01 -04003125 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07003126 public void testDontAutogroupIfCritical() throws Exception {
3127 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3128 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
3129 mService.addEnqueuedNotification(r);
3130 NotificationManagerService.PostNotificationRunnable runnable =
3131 mService.new PostNotificationRunnable(r.getKey());
3132 runnable.run();
3133
3134 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
3135 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
3136 runnable = mService.new PostNotificationRunnable(r.getKey());
3137 mService.addEnqueuedNotification(r);
3138
3139 runnable.run();
3140 waitForIdle();
3141
3142 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
3143 }
3144
3145 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04003146 public void testNoFakeColorizedPermission() throws Exception {
3147 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
3148 Notification.Builder nb = new Notification.Builder(mContext,
3149 mTestNotificationChannel.getId())
3150 .setContentTitle("foo")
3151 .setColorized(true)
3152 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
3153 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003154 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
3155 "testNoFakeColorizedPermission", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003156 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04003157 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3158
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003159 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds24edc002020-01-29 16:35:32 -05003160 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003161 waitForIdle();
3162
Julia Reynolds503ed942017-10-04 16:04:56 -04003163 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003164 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003165
3166 assertFalse(posted.getNotification().isColorized());
3167 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003168
3169 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003170 public void testGetNotificationCountLocked() {
3171 String sampleTagToExclude = null;
3172 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003173 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003174 NotificationRecord r =
3175 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003176 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003177
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003178 }
3179 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003180 NotificationRecord r =
3181 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003182 mService.addNotification(r);
Julia Reynolds24edc002020-01-29 16:35:32 -05003183 sampleTagToExclude = r.getSbn().getTag();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003184 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003185 }
3186
3187 // another package
3188 Notification n =
3189 new Notification.Builder(mContext, mTestNotificationChannel.getId())
3190 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3191 .build();
3192
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003193 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
3194 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003195 NotificationRecord otherPackage =
3196 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003197 mService.addEnqueuedNotification(otherPackage);
3198 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003199
3200 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003201 // anything that's currently enqueued or posted
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003202 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003203 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003204 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003205 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003206 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003207
3208 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003209 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04003210 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003211
3212 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003213 assertEquals(39, mService.getNotificationCountLocked(
3214 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003215 }
3216
3217 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04003218 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003219 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003220 mService.addNotification(r);
3221 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003222
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003223 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003224 }
3225
3226 @Test
3227 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003228 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3229 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003230 mService.addNotification(r);
3231 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003232
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003233 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003234 }
3235
3236 @Test
3237 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003238 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3239 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003240 mService.addNotification(r);
3241 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003242
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003243 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003244 }
3245
3246 @Test
3247 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04003248 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003249 NotificationManagerService.WorkerHandler handler = mock(
3250 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003251 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003252
3253 Map<String, Answer> answers = getSignalExtractorSideEffects();
3254 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04003255 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003256 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003257 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003258
3259 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
3260
Julia Reynolds503ed942017-10-04 16:04:56 -04003261 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003262 }
3263 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
3264 }
3265
3266 @Test
3267 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003268 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003269 NotificationManagerService.WorkerHandler handler = mock(
3270 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003271 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003272
3273 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003274 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003275
Julia Reynolds503ed942017-10-04 16:04:56 -04003276 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003277 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003278 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003279
3280 @Test
3281 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04003282 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003283 + "<ranking></ranking>"
3284 + "<enabled_listeners>"
3285 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3286 + "</enabled_listeners>"
3287 + "<enabled_assistants>"
3288 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3289 + "</enabled_assistants>"
3290 + "<dnd_apps>"
3291 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3292 + "</dnd_apps>"
3293 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003294 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003295 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3296 false,
3297 UserHandle.USER_ALL);
3298 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3299 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3300 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003301
3302 // numbers are inflated for setup
3303 verify(mListeners, times(1)).migrateToXml();
3304 verify(mConditionProviders, times(1)).migrateToXml();
3305 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003306 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003307 }
3308
3309 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003310 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
3311 final String upgradeXml = "<notification-policy version=\"1\">"
3312 + "<snoozed-notifications>></snoozed-notifications>"
3313 + "</notification-policy>";
3314 mService.readPolicyXml(
3315 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3316 false,
3317 UserHandle.USER_ALL);
Julia Reynolds9050d9a2020-02-20 09:38:05 -05003318 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong());
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003319 }
3320
3321 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003322 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
3323 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003324 + "<ranking></ranking>"
3325 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003326 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003327 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
3328 false,
3329 UserHandle.USER_ALL);
3330 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
3331 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
3332 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003333
3334 // numbers are inflated for setup
3335 verify(mListeners, times(2)).migrateToXml();
3336 verify(mConditionProviders, times(2)).migrateToXml();
3337 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003338 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003339 }
3340
Annie Meng8b646fd2019-02-01 18:46:42 +00003341 @Test
3342 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3343 final String policyXml = "<notification-policy version=\"1\">"
3344 + "<ranking></ranking>"
3345 + "<enabled_listeners>"
3346 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3347 + "</enabled_listeners>"
3348 + "<enabled_assistants>"
3349 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3350 + "</enabled_assistants>"
3351 + "<dnd_apps>"
3352 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3353 + "</dnd_apps>"
3354 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003355 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00003356 mService.readPolicyXml(
3357 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3358 true,
3359 10);
3360 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3361 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3362 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3363 }
3364
3365 @Test
3366 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3367 final String policyXml = "<notification-policy version=\"1\">"
3368 + "<ranking></ranking>"
3369 + "<enabled_listeners>"
3370 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3371 + "</enabled_listeners>"
3372 + "<enabled_assistants>"
3373 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3374 + "</enabled_assistants>"
3375 + "<dnd_apps>"
3376 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3377 + "</dnd_apps>"
3378 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003379 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003380 mService.readPolicyXml(
3381 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3382 true,
3383 10);
3384 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3385 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3386 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3387 }
Beverlyd4f96492017-08-02 13:36:11 -04003388
3389 @Test
3390 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3391 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003392 mService.mZenModeHelper = mZenModeHelper;
3393 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003394 new Intent(Intent.ACTION_LOCALE_CHANGED));
3395
3396 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3397 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003398
3399 @Test
3400 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003401 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003402 final ApplicationInfo legacy = new ApplicationInfo();
3403 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3404 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3405 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003406 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3407 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003408 getContext().setMockPackageManager(mPackageManagerClient);
3409
3410 Notification.Builder nb = new Notification.Builder(mContext,
3411 NotificationChannel.DEFAULT_CHANNEL_ID)
3412 .setContentTitle("foo")
3413 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003414 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003415 .setPriority(Notification.PRIORITY_MIN);
3416
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003417 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3418 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds24edc002020-01-29 16:35:32 -05003419 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null,
3420 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003421
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003422 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3423 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003424 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003425
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003426 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003427 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003428
3429 nb = new Notification.Builder(mContext)
3430 .setContentTitle("foo")
3431 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003432 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003433 .setPriority(Notification.PRIORITY_MIN);
3434
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003435 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3436 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003437 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003438
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003439 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3440 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003441 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3442 waitForIdle();
3443 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003444 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003445
3446 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003447 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003448 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3449 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003450
3451 @Test
3452 public void testStats_updatedOnDirectReply() throws Exception {
3453 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3454 mService.addNotification(r);
3455
3456 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3457 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Julia Reynolds24edc002020-01-29 16:35:32 -05003458 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.getSbn()));
Will Brockman9918db92020-03-06 16:48:39 -05003459
3460 assertEquals(1, mNotificationRecordLogger.numCalls());
3461 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
3462 mNotificationRecordLogger.event(0));
Julia Reynolds503ed942017-10-04 16:04:56 -04003463 }
3464
3465 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003466 public void testStats_updatedOnUserExpansion() throws Exception {
3467 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003468 mService.addNotification(r);
3469
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003470 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3471 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003472 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3473 eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003474 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003475
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003476 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3477 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003478 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3479 eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003480 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Will Brockman9918db92020-03-06 16:48:39 -05003481
3482 assertEquals(2, mNotificationRecordLogger.numCalls());
3483 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
3484 mNotificationRecordLogger.event(0));
3485 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
3486 mNotificationRecordLogger.event(1));
Julia Reynolds503ed942017-10-04 16:04:56 -04003487 }
3488
3489 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003490 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3491 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3492 mService.addNotification(r);
3493
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003494 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3495 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003496 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Julia Reynolds24edc002020-01-29 16:35:32 -05003497 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(false),
3498 eq((true)));
Tony Makeda84a72018-11-19 17:01:32 +00003499
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003500 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3501 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003502 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003503 verify(mAssistants).notifyAssistantExpansionChangedLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003504 eq(r.getSbn()), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003505 }
3506
3507 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003508 public void testStats_updatedOnViewSettings() throws Exception {
3509 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3510 mService.addNotification(r);
3511
3512 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3513 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3514 }
3515
3516 @Test
3517 public void testStats_updatedOnVisibilityChanged() throws Exception {
3518 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3519 mService.addNotification(r);
3520
Dieter Hsud39f0d52018-04-14 02:08:30 +08003521 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003522 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3523 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
Julia Reynolds24edc002020-01-29 16:35:32 -05003524 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(true));
Julia Reynolds503ed942017-10-04 16:04:56 -04003525 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3526 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3527 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
Julia Reynolds24edc002020-01-29 16:35:32 -05003528 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(false));
Julia Reynolds503ed942017-10-04 16:04:56 -04003529 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3530 }
3531
3532 @Test
3533 public void testStats_dismissalSurface() throws Exception {
3534 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Will Brockman4f0f9d22020-02-23 21:18:11 -05003535 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003536 mService.addNotification(r);
3537
Dieter Hsud39f0d52018-04-14 02:08:30 +08003538 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003539 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3540 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003541 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003542 waitForIdle();
3543
3544 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
Will Brockman75c60572020-01-31 10:30:27 -05003545
3546 // Using mService.addNotification() does not generate a NotificationRecordLogger log,
3547 // so we only get the cancel notification.
Will Brockman9918db92020-03-06 16:48:39 -05003548 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockman75c60572020-01-31 10:30:27 -05003549
Will Brockman75c60572020-01-31 10:30:27 -05003550 assertEquals(
3551 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
Will Brockman9918db92020-03-06 16:48:39 -05003552 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05003553 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003554 }
3555
3556 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003557 public void testStats_dismissalSentiment() throws Exception {
3558 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3559 mService.addNotification(r);
3560
3561 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003562 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3563 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003564 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3565 waitForIdle();
3566
3567 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3568 r.getStats().getDismissalSentiment());
3569 }
3570
3571 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003572 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003573 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3574 mService.addNotification(r);
3575 NotificationManagerService.WorkerHandler handler = mock(
3576 NotificationManagerService.WorkerHandler.class);
3577 mService.setHandler(handler);
3578
Julia Reynolds70aaea72018-07-13 13:38:34 -04003579 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3580
Julia Reynolds503ed942017-10-04 16:04:56 -04003581 Bundle signals = new Bundle();
3582 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003583 USER_SENTIMENT_NEGATIVE);
3584 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003585 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003586 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3587
3588 waitForIdle();
3589
3590 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3591 }
3592
3593 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003594 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003595 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3596 mService.addNotification(r);
3597 NotificationManagerService.WorkerHandler handler = mock(
3598 NotificationManagerService.WorkerHandler.class);
3599 mService.setHandler(handler);
3600
3601 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003602 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003603 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003604 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003605 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3606 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3607
3608 waitForIdle();
3609
3610 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3611 verify(handler, times(1)).scheduleCancelNotification(any());
3612 }
3613
3614 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003615 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3616 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3617 mService.addEnqueuedNotification(r);
3618 NotificationManagerService.WorkerHandler handler = mock(
3619 NotificationManagerService.WorkerHandler.class);
3620 mService.setHandler(handler);
3621 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3622
3623 Bundle signals = new Bundle();
3624 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3625 USER_SENTIMENT_NEGATIVE);
3626 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003627 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003628 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3629
3630 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3631 }
3632
3633 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003634 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003635 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3636 mService.addEnqueuedNotification(r);
3637 NotificationManagerService.WorkerHandler handler = mock(
3638 NotificationManagerService.WorkerHandler.class);
3639 mService.setHandler(handler);
3640 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3641
3642 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003643 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003644 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003645 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05003646 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3647
3648 assertEquals(IMPORTANCE_LOW, r.getImportance());
3649 }
3650
3651 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003652 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3653 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3654 mService.addEnqueuedNotification(r);
3655 NotificationManagerService.WorkerHandler handler = mock(
3656 NotificationManagerService.WorkerHandler.class);
3657 mService.setHandler(handler);
3658 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3659
3660 Bundle signals = new Bundle();
3661 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3662 USER_SENTIMENT_NEGATIVE);
3663 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003664 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003665 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3666
3667 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3668
3669 waitForIdle();
3670
3671 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3672 }
3673
3674 @Test
3675 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3676 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3677 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003678 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3679
3680 Bundle signals = new Bundle();
3681 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3682 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003683 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003684 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds503ed942017-10-04 16:04:56 -04003685 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3686
3687 waitForIdle();
3688
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003689 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003690 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003691
3692 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003693 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3694 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3695 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003696 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003697
3698 Bundle signals = new Bundle();
3699 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003700 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003701 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003702 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003703 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3704
3705 waitForIdle();
3706
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003707 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003708 }
3709
3710 @Test
3711 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3712 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3713 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003714 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003715
3716 Bundle signals = new Bundle();
3717 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003718 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003719 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003720 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003721 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3722
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003723 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003724 }
3725
3726 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003727 public void testRestore() throws Exception {
3728 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003729 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003730 assertEquals(1, mService.countSystemChecks - systemChecks);
3731 }
3732
3733 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003734 public void testBackupEmptySound() throws Exception {
3735 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3736 channel.setSound(Uri.EMPTY, null);
3737
3738 XmlSerializer serializer = new FastXmlSerializer();
3739 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3740 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3741 channel.writeXmlForBackup(serializer, getContext());
3742
3743 XmlPullParser parser = Xml.newPullParser();
3744 parser.setInput(new BufferedInputStream(
3745 new ByteArrayInputStream(baos.toByteArray())), null);
3746 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3747 restored.populateFromXmlForRestore(parser, getContext());
3748
3749 assertNull(restored.getSound());
3750 }
3751
3752 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003753 public void testBackup() throws Exception {
3754 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04003755 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3756 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003757 mBinderService.getBackupPayload(1);
3758 assertEquals(1, mService.countSystemChecks - systemChecks);
3759 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003760
3761 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003762 public void testEmptyVibration_noException() throws Exception {
3763 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3764 channel.setVibrationPattern(new long[0]);
3765
3766 XmlSerializer serializer = new FastXmlSerializer();
3767 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3768 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3769 channel.writeXml(serializer);
3770 }
3771
3772 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003773 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003774 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003775 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003776 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3777 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003778 message1.setData("",
3779 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003780 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003781 message2.setData("",
3782 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003783
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003784 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003785 .setContentTitle("foo")
3786 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3787 .setStyle(new Notification.MessagingStyle("")
3788 .addMessage(message1)
3789 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003790 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3791 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003792
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003793 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003794 reset(mUgm);
3795 reset(mUgmInternal);
3796 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003797 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003798 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003799 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003800 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003801 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003802 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3803
3804 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003805 .setContentTitle("foo")
3806 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3807 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003808 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3809 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003810
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003811 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003812 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003813 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003814 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003815 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3816 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003817
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003818 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003819 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003820 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003821 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003822 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003823 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003824
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003825 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003826 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003827 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003828 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003829 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003830 anyInt(), anyInt());
3831 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003832
3833 @Test
Julia Reynoldsea58c202020-02-03 12:52:49 -05003834 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
3835 NotificationChannel c = new NotificationChannel(
3836 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
3837 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3838 Message message1 = new Message("", 0, "");
3839 message1.setData("",
3840 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
3841
3842 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
3843 .setContentTitle("foo")
3844 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3845 .setStyle(new Notification.MessagingStyle("")
3846 .addMessage(message1));
3847 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3848 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
3849
3850 doThrow(new SecurityException("no access")).when(mUgm)
3851 .grantUriPermissionFromOwner(
3852 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
3853
3854 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
3855 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM);
3856
3857 // yay, no crash
3858 }
3859
3860 @Test
Robin Leed107af62018-04-27 13:55:56 +02003861 public void testVisitUris() throws Exception {
3862 final Uri audioContents = Uri.parse("content://com.example/audio");
3863 final Uri backgroundImage = Uri.parse("content://com.example/background");
3864
3865 Bundle extras = new Bundle();
3866 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3867 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3868
3869 Notification n = new Notification.Builder(mContext, "a")
3870 .setContentTitle("notification with uris")
3871 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3872 .addExtras(extras)
3873 .build();
3874
3875 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3876 n.visitUris(visitor);
3877 verify(visitor, times(1)).accept(eq(audioContents));
3878 verify(visitor, times(1)).accept(eq(backgroundImage));
3879 }
3880
3881 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003882 public void testSetNotificationPolicy_preP_setOldFields() {
3883 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3884 mService.mZenModeHelper = mZenModeHelper;
3885 NotificationManager.Policy userPolicy =
3886 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3887 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3888
3889 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3890 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3891
3892 int expected = SUPPRESSED_EFFECT_BADGE
3893 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003894 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3895 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003896 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3897
3898 assertEquals(expected, actual);
3899 }
3900
3901 @Test
3902 public void testSetNotificationPolicy_preP_setNewFields() {
3903 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3904 mService.mZenModeHelper = mZenModeHelper;
3905 NotificationManager.Policy userPolicy =
3906 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3907 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3908
3909 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3910 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3911
3912 int expected = SUPPRESSED_EFFECT_BADGE;
3913 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3914
3915 assertEquals(expected, actual);
3916 }
3917
3918 @Test
3919 public void testSetNotificationPolicy_preP_setOldNewFields() {
3920 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3921 mService.mZenModeHelper = mZenModeHelper;
3922 NotificationManager.Policy userPolicy =
3923 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3924 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3925
3926 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3927 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3928
3929 int expected =
3930 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3931 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3932
3933 assertEquals(expected, actual);
3934 }
3935
3936 @Test
3937 public void testSetNotificationPolicy_P_setOldFields() {
3938 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3939 mService.mZenModeHelper = mZenModeHelper;
3940 NotificationManager.Policy userPolicy =
3941 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3942 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3943
3944 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3945 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3946
3947 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3948 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3949 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3950 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3951
3952 assertEquals(expected, actual);
3953 }
3954
3955 @Test
3956 public void testSetNotificationPolicy_P_setNewFields() {
3957 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3958 mService.mZenModeHelper = mZenModeHelper;
3959 NotificationManager.Policy userPolicy =
3960 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3961 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3962
3963 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3964 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3965 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3966
3967 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3968 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3969 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3970 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3971
3972 assertEquals(expected, actual);
3973 }
3974
3975 @Test
3976 public void testSetNotificationPolicy_P_setOldNewFields() {
3977 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3978 mService.mZenModeHelper = mZenModeHelper;
3979 NotificationManager.Policy userPolicy =
3980 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3981 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3982
3983 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3984 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3985
3986 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3987 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3988
3989 assertEquals(expected, actual);
3990
3991 appPolicy = new NotificationManager.Policy(0, 0, 0,
3992 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3993 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3994
3995 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3996 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3997 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3998
3999 assertEquals(expected, actual);
4000 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05004001
4002 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04004003 public void testVisualDifference_foreground() {
4004 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4005 .setContentTitle("foo");
4006 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4007 nb1.build(), new UserHandle(mUid), null, 0);
4008 NotificationRecord r1 =
4009 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4010
4011 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4012 .setFlag(FLAG_FOREGROUND_SERVICE, true)
4013 .setContentTitle("bar");
4014 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4015 nb2.build(), new UserHandle(mUid), null, 0);
4016 NotificationRecord r2 =
4017 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4018
4019 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4020 }
4021
4022 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004023 public void testVisualDifference_diffTitle() {
4024 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4025 .setContentTitle("foo");
4026 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4027 nb1.build(), new UserHandle(mUid), null, 0);
4028 NotificationRecord r1 =
4029 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4030
4031 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4032 .setContentTitle("bar");
4033 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4034 nb2.build(), new UserHandle(mUid), null, 0);
4035 NotificationRecord r2 =
4036 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4037
4038 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4039 }
4040
4041 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004042 public void testVisualDifference_inboxStyle() {
4043 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4044 .setStyle(new Notification.InboxStyle()
4045 .addLine("line1").addLine("line2"));
4046 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4047 nb1.build(), new UserHandle(mUid), null, 0);
4048 NotificationRecord r1 =
4049 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4050
4051 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4052 .setStyle(new Notification.InboxStyle()
4053 .addLine("line1").addLine("line2_changed"));
4054 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4055 nb2.build(), new UserHandle(mUid), null, 0);
4056 NotificationRecord r2 =
4057 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4058
4059 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
4060
4061 Notification.Builder nb3 = new Notification.Builder(mContext, "")
4062 .setStyle(new Notification.InboxStyle()
4063 .addLine("line1"));
4064 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4065 nb3.build(), new UserHandle(mUid), null, 0);
4066 NotificationRecord r3 =
4067 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
4068
4069 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
4070
4071 Notification.Builder nb4 = new Notification.Builder(mContext, "")
4072 .setStyle(new Notification.InboxStyle()
4073 .addLine("line1").addLine("line2").addLine("line3"));
4074 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4075 nb4.build(), new UserHandle(mUid), null, 0);
4076 NotificationRecord r4 =
4077 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
4078
4079 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
4080
4081 Notification.Builder nb5 = new Notification.Builder(mContext, "")
4082 .setContentText("not an inbox");
4083 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4084 nb5.build(), new UserHandle(mUid), null, 0);
4085 NotificationRecord r5 =
4086 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
4087
4088 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
4089 }
4090
4091 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004092 public void testVisualDifference_diffText() {
4093 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4094 .setContentText("foo");
4095 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4096 nb1.build(), new UserHandle(mUid), null, 0);
4097 NotificationRecord r1 =
4098 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4099
4100 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4101 .setContentText("bar");
4102 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4103 nb2.build(), new UserHandle(mUid), null, 0);
4104 NotificationRecord r2 =
4105 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4106
4107 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4108 }
4109
4110 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004111 public void testVisualDifference_sameText() {
4112 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4113 .setContentText("foo");
4114 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4115 nb1.build(), new UserHandle(mUid), null, 0);
4116 NotificationRecord r1 =
4117 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4118
4119 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4120 .setContentText("foo");
4121 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4122 nb2.build(), new UserHandle(mUid), null, 0);
4123 NotificationRecord r2 =
4124 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4125
4126 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4127 }
4128
4129 @Test
4130 public void testVisualDifference_sameTextButStyled() {
4131 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4132 .setContentText(Html.fromHtml("<b>foo</b>"));
4133 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4134 nb1.build(), new UserHandle(mUid), null, 0);
4135 NotificationRecord r1 =
4136 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4137
4138 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4139 .setContentText(Html.fromHtml("<b>foo</b>"));
4140 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4141 nb2.build(), new UserHandle(mUid), null, 0);
4142 NotificationRecord r2 =
4143 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4144
4145 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4146 }
4147
4148 @Test
4149 public void testVisualDifference_diffTextButStyled() {
4150 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4151 .setContentText(Html.fromHtml("<b>foo</b>"));
4152 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4153 nb1.build(), new UserHandle(mUid), null, 0);
4154 NotificationRecord r1 =
4155 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4156
4157 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4158 .setContentText(Html.fromHtml("<b>bar</b>"));
4159 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4160 nb2.build(), new UserHandle(mUid), null, 0);
4161 NotificationRecord r2 =
4162 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4163
4164 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4165 }
4166
4167 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004168 public void testVisualDifference_diffProgress() {
4169 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4170 .setProgress(100, 90, false);
4171 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4172 nb1.build(), new UserHandle(mUid), null, 0);
4173 NotificationRecord r1 =
4174 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4175
4176 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4177 .setProgress(100, 100, false);
4178 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4179 nb2.build(), new UserHandle(mUid), null, 0);
4180 NotificationRecord r2 =
4181 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4182
4183 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4184 }
4185
4186 @Test
4187 public void testVisualDifference_diffProgressNotDone() {
4188 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4189 .setProgress(100, 90, false);
4190 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4191 nb1.build(), new UserHandle(mUid), null, 0);
4192 NotificationRecord r1 =
4193 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4194
4195 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4196 .setProgress(100, 91, false);
4197 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4198 nb2.build(), new UserHandle(mUid), null, 0);
4199 NotificationRecord r2 =
4200 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4201
4202 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4203 }
Beverly5a20a5e2018-03-06 15:02:44 -05004204
4205 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004206 public void testVisualDifference_sameProgressStillDone() {
4207 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4208 .setProgress(100, 100, false);
4209 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4210 nb1.build(), new UserHandle(mUid), null, 0);
4211 NotificationRecord r1 =
4212 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4213
4214 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4215 .setProgress(100, 100, false);
4216 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4217 nb2.build(), new UserHandle(mUid), null, 0);
4218 NotificationRecord r2 =
4219 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4220
4221 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4222 }
4223
4224 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004225 public void testVisualDifference_summary() {
4226 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4227 .setGroup("bananas")
4228 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4229 .setContentText("foo");
4230 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4231 nb1.build(), new UserHandle(mUid), null, 0);
4232 NotificationRecord r1 =
4233 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4234
4235 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4236 .setGroup("bananas")
4237 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4238 .setContentText("bar");
4239 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4240 nb2.build(), new UserHandle(mUid), null, 0);
4241 NotificationRecord r2 =
4242 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4243
4244 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4245 }
4246
4247 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04004248 public void testVisualDifference_summaryNewNotification() {
4249 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4250 .setGroup("bananas")
4251 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4252 .setContentText("bar");
4253 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4254 nb2.build(), new UserHandle(mUid), null, 0);
4255 NotificationRecord r2 =
4256 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4257
4258 assertFalse(mService.isVisuallyInterruptive(null, r2));
4259 }
4260
4261 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05004262 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
4263 // post 2 notification from this package
4264 final NotificationRecord notif1 = generateNotificationRecord(
4265 mTestNotificationChannel, 1, null, true);
4266 final NotificationRecord notif2 = generateNotificationRecord(
4267 mTestNotificationChannel, 2, null, false);
4268 mService.addNotification(notif1);
4269 mService.addNotification(notif2);
4270
4271 // on broadcast, hide the 2 notifications
4272 mService.simulatePackageSuspendBroadcast(true, PKG);
4273 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
4274 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4275 assertEquals(2, captorHide.getValue().size());
4276
4277 // on broadcast, unhide the 2 notifications
4278 mService.simulatePackageSuspendBroadcast(false, PKG);
4279 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
4280 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4281 assertEquals(2, captorUnhide.getValue().size());
4282 }
4283
4284 @Test
4285 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
4286 // post 2 notification from this package
4287 final NotificationRecord notif1 = generateNotificationRecord(
4288 mTestNotificationChannel, 1, null, true);
4289 final NotificationRecord notif2 = generateNotificationRecord(
4290 mTestNotificationChannel, 2, null, false);
4291 mService.addNotification(notif1);
4292 mService.addNotification(notif2);
4293
4294 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4295 mService.simulatePackageSuspendBroadcast(true, "test_package");
4296 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4297 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4298 assertEquals(0, captor.getValue().size());
4299 }
Kristian Monsen05f34792018-04-09 10:27:16 +02004300
4301 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004302 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
4303 // Post 2 notifications from 2 packages
4304 NotificationRecord pkgA = new NotificationRecord(mContext,
4305 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4306 mService.addNotification(pkgA);
4307 NotificationRecord pkgB = new NotificationRecord(mContext,
4308 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4309 mService.addNotification(pkgB);
4310
4311 // on broadcast, hide one of the packages
4312 mService.simulatePackageDistractionBroadcast(
4313 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
4314 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4315 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4316 assertEquals(1, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004317 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004318
4319 // on broadcast, unhide the package
4320 mService.simulatePackageDistractionBroadcast(
4321 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
4322 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4323 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4324 assertEquals(1, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004325 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004326 }
4327
4328 @Test
4329 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
4330 // Post 2 notifications from 2 packages
4331 NotificationRecord pkgA = new NotificationRecord(mContext,
4332 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4333 mService.addNotification(pkgA);
4334 NotificationRecord pkgB = new NotificationRecord(mContext,
4335 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4336 mService.addNotification(pkgB);
4337
4338 // on broadcast, hide one of the packages
4339 mService.simulatePackageDistractionBroadcast(
4340 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
4341 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004342
4343 // should be called only once.
4344 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004345 assertEquals(2, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004346 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
4347 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004348
4349 // on broadcast, unhide the package
4350 mService.simulatePackageDistractionBroadcast(
4351 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
4352 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004353
4354 // should be called only once.
4355 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004356 assertEquals(2, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004357 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
4358 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004359 }
4360
4361 @Test
4362 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
4363 // post notification from this package
4364 final NotificationRecord notif1 = generateNotificationRecord(
4365 mTestNotificationChannel, 1, null, true);
4366 mService.addNotification(notif1);
4367
4368 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4369 mService.simulatePackageDistractionBroadcast(
4370 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
4371 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4372 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4373 assertEquals(0, captor.getValue().size());
4374 }
4375
4376 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004377 public void testCanUseManagedServicesNullPkg() {
4378 assertEquals(true, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004379 }
4380
Kristian Monsen05f34792018-04-09 10:27:16 +02004381
4382 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004383 public void testCanUseManagedServicesNoValidPkg() {
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004384 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4385 }
4386
4387 @Test
4388 public void testCanUseManagedServices_hasPermission() throws Exception {
4389 when(mPackageManager.checkPermission("perm", "pkg", 0))
4390 .thenReturn(PackageManager.PERMISSION_GRANTED);
4391
4392 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4393 }
4394
4395 @Test
4396 public void testCanUseManagedServices_noPermission() throws Exception {
4397 when(mPackageManager.checkPermission("perm", "pkg", 0))
4398 .thenReturn(PackageManager.PERMISSION_DENIED);
4399
4400 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4401 }
4402
4403 @Test
4404 public void testCanUseManagedServices_permDoesNotMatter() {
4405 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004406 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004407
4408 @Test
4409 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4410 final NotificationRecord r = generateNotificationRecord(
4411 mTestNotificationChannel, 1, null, true);
4412 r.setTextChanged(true);
4413 mService.addNotification(r);
4414
4415 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4416 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4417 new NotificationVisibility[]{});
4418
4419 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4420 }
4421
4422 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05004423 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
4424 final NotificationRecord r = generateNotificationRecord(
4425 mTestNotificationChannel, 1, null, true);
4426 r.setTextChanged(true);
Will Brockman4f0f9d22020-02-23 21:18:11 -05004427 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004428 mService.addNotification(r);
4429
4430 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4431 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4432 new NotificationVisibility[]{});
4433
Will Brockman9918db92020-03-06 16:48:39 -05004434 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004435 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
Will Brockman9918db92020-03-06 16:48:39 -05004436 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004437 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004438
4439 mService.mNotificationDelegate.onNotificationVisibilityChanged(
4440 new NotificationVisibility[]{},
4441 new NotificationVisibility[]
4442 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
4443 );
4444
Will Brockman9918db92020-03-06 16:48:39 -05004445 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004446 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
Will Brockman9918db92020-03-06 16:48:39 -05004447 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004448 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004449 }
4450
4451 @Test
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004452 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4453 throws RemoteException {
4454 final NotificationRecord r = generateNotificationRecord(
4455 mTestNotificationChannel, 1, null, true);
4456 r.setTextChanged(true);
4457 mService.addNotification(r);
4458
4459 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4460
4461 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4462 }
4463
4464 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004465 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004466 throws RemoteException {
4467 final NotificationRecord r = generateNotificationRecord(
4468 mTestNotificationChannel, 1, null, true);
4469 r.setInterruptive(true);
4470 mService.addNotification(r);
4471
4472 mService.maybeRecordInterruptionLocked(r);
4473 mService.maybeRecordInterruptionLocked(r);
4474
4475 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4476 anyString(), anyString(), anyInt());
Julia Reynoldsfd9f8342020-03-06 09:36:00 -05004477 verify(mHistoryManager, times(1)).addNotification(any());
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004478 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004479
4480 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004481 public void testBubble() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004482 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4483 assertFalse(mBinderService.areBubblesAllowed(PKG));
4484 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4485 BUBBLE_PREFERENCE_NONE);
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004486 }
4487
4488 @Test
Mady Mellora92268c2020-03-09 17:25:08 -07004489 public void testUserApprovedBubblesForPackageSelected() throws Exception {
4490 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
4491 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4492 BUBBLE_PREFERENCE_SELECTED);
4493 }
4494
4495 @Test
4496 public void testUserApprovedBubblesForPackageAll() throws Exception {
4497 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
4498 assertTrue(mBinderService.areBubblesAllowed(PKG));
4499 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4500 BUBBLE_PREFERENCE_ALL);
Mady Mellor9db685a2019-01-23 13:23:37 -08004501 }
4502
4503 @Test
4504 public void testUserRejectsBubblesForPackage() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004505 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4506 assertFalse(mBinderService.areBubblesAllowed(PKG));
Mady Mellor9db685a2019-01-23 13:23:37 -08004507 }
4508
4509 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004510 public void testIsCallerInstantApp_primaryUser() throws Exception {
4511 ApplicationInfo info = new ApplicationInfo();
4512 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4513 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004514 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004515
Julia Reynolds268647a2018-10-25 16:54:27 -04004516 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004517
4518 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004519 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004520 }
4521
4522 @Test
4523 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4524 ApplicationInfo info = new ApplicationInfo();
4525 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4526 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4527 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004528 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004529
Julia Reynolds268647a2018-10-25 16:54:27 -04004530 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004531 }
4532
4533 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004534 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4535 ApplicationInfo info = new ApplicationInfo();
4536 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004537 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004538 .thenReturn(info);
4539 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4540
4541 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4542
4543 info.privateFlags = 0;
4544 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4545 }
4546
4547 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004548 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4549 ApplicationInfo info = new ApplicationInfo();
4550 info.uid = Binder.getCallingUid();
4551 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4552 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4553
4554 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4555
4556 assertEquals(info.uid, actualUid);
4557 }
4558
4559 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004560 public void testResolveNotificationUid_sameApp() throws Exception {
4561 ApplicationInfo info = new ApplicationInfo();
4562 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004563 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004564
4565 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4566
4567 assertEquals(info.uid, actualUid);
4568 }
4569
4570 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004571 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004572 ApplicationInfo info = new ApplicationInfo();
4573 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004574 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004575
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004576 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4577
4578 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004579 }
4580
4581 @Test
4582 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4583 ApplicationInfo info = new ApplicationInfo();
4584 info.uid = 1356347;
4585 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4586
4587 try {
4588 mService.resolveNotificationUid("caller", "caller", 9, 0);
4589 fail("Incorrect uid didn't throw security exception");
4590 } catch (SecurityException e) {
4591 // yay
4592 }
4593 }
4594
4595 @Test
4596 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4597 int expectedUid = 123;
4598
4599 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4600 mService.setPreferencesHelper(mPreferencesHelper);
4601 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4602 .thenReturn(true);
4603
4604 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4605 }
4606
4607 @Test
4608 public void testResolveNotificationUid_androidAllowed() throws Exception {
4609 int expectedUid = 123;
4610
4611 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4612 // no delegate
4613
4614 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4615 }
4616
4617 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004618 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4619 final String notReal = "NOT REAL";
4620 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4621 PackageManager.NameNotFoundException.class);
4622 ApplicationInfo ai = new ApplicationInfo();
4623 ai.uid = -1;
4624 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4625
Julia Reynolds24edc002020-01-29 16:35:32 -05004626 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004627 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004628 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4629 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004630 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4631 fail("can't post notifications for nonexistent packages, even if you exist");
4632 } catch (SecurityException e) {
4633 // yay
4634 }
4635 }
4636
4637 @Test
4638 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4639 final String notReal = "NOT REAL";
4640 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4641 PackageManager.NameNotFoundException.class);
4642 ApplicationInfo ai = new ApplicationInfo();
4643 ai.uid = -1;
4644 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4645
4646 // unlike the post case, ignore instead of throwing
Julia Reynolds24edc002020-01-29 16:35:32 -05004647 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004648
4649 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4650 sbn.getId(), sbn.getUserId());
4651 }
4652
4653 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004654 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4655 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4656 // no delegate
4657
4658 try {
4659 mService.resolveNotificationUid("caller", "target", 9, 0);
4660 fail("Incorrect uid didn't throw security exception");
4661 } catch (SecurityException e) {
4662 // yay
4663 }
4664 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004665
4666 @Test
4667 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4668 Notification n = new Notification.Builder(mContext, "").build();
4669 n.flags |= FLAG_FOREGROUND_SERVICE;
4670
4671 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4672 n, new UserHandle(mUid), null, 0);
4673 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4674
4675 mService.addEnqueuedNotification(r);
4676
4677 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004678 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004679
4680 waitForIdle();
4681
4682 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4683 }
4684
4685 @Test
4686 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4687 Notification n = new Notification.Builder(mContext, "").build();
4688 n.flags |= FLAG_FOREGROUND_SERVICE;
4689
4690 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4691 n, new UserHandle(mUid), null, 0);
4692 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4693
4694 mService.addNotification(r);
4695
4696 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004697 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004698
4699 waitForIdle();
4700
4701 ArgumentCaptor<NotificationRecord> captor =
4702 ArgumentCaptor.forClass(NotificationRecord.class);
4703 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4704
4705 assertEquals(0, captor.getValue().getNotification().flags);
4706 }
Beverly58b24532018-10-02 09:08:23 -04004707
4708 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004709 public void testAllowForegroundCustomToasts() throws Exception {
Beverly58b24532018-10-02 09:08:23 -04004710 final String testPackage = "testPackageName";
4711 assertEquals(0, mService.mToastQueue.size());
4712 mService.isSystemUid = false;
4713
4714 // package is not suspended
4715 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4716 .thenReturn(false);
4717
4718 // notifications from this package are blocked by the user
4719 mService.setPreferencesHelper(mPreferencesHelper);
4720 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4721
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004722 setAppInForegroundForToasts(mUid, true);
Beverly58b24532018-10-02 09:08:23 -04004723
4724 // enqueue toast -> toast should still enqueue
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004725 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004726 new TestableToastCallback(), 2000, 0);
4727 assertEquals(1, mService.mToastQueue.size());
4728 }
4729
4730 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004731 public void testDisallowBackgroundCustomToasts() throws Exception {
4732 final String testPackage = "testPackageName";
4733 assertEquals(0, mService.mToastQueue.size());
4734 mService.isSystemUid = false;
4735
4736 // package is not suspended
4737 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4738 .thenReturn(false);
4739
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004740 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004741
4742 // enqueue toast -> no toasts enqueued
4743 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
4744 new TestableToastCallback(), 2000, 0);
4745 assertEquals(0, mService.mToastQueue.size());
4746 }
4747
4748 @Test
4749 public void testAllowForegroundTextToasts() throws Exception {
4750 final String testPackage = "testPackageName";
4751 assertEquals(0, mService.mToastQueue.size());
4752 mService.isSystemUid = false;
4753
4754 // package is not suspended
4755 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4756 .thenReturn(false);
4757
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004758 setAppInForegroundForToasts(mUid, true);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004759
4760 // enqueue toast -> toast should still enqueue
4761 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4762 "Text", 2000, 0, null);
4763 assertEquals(1, mService.mToastQueue.size());
4764 }
4765
4766 @Test
4767 public void testAllowBackgroundTextToasts() throws Exception {
4768 final String testPackage = "testPackageName";
4769 assertEquals(0, mService.mToastQueue.size());
4770 mService.isSystemUid = false;
4771
4772 // package is not suspended
4773 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4774 .thenReturn(false);
4775
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004776 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004777
4778 // enqueue toast -> toast should still enqueue
4779 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4780 "Text", 2000, 0, null);
4781 assertEquals(1, mService.mToastQueue.size());
4782 }
4783
4784 @Test
4785 public void testTextToastsCallStatusBar() throws Exception {
4786 final String testPackage = "testPackageName";
4787 assertEquals(0, mService.mToastQueue.size());
4788 mService.isSystemUid = false;
4789
4790 // package is not suspended
4791 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4792 .thenReturn(false);
4793
4794 // enqueue toast -> no toasts enqueued
4795 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4796 "Text", 2000, 0, null);
Bernardo Rufino78f5d832020-04-03 11:50:23 +01004797 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
Bernardo Rufino18725b62020-01-21 14:12:43 +00004798 }
4799
4800 @Test
Beverly58b24532018-10-02 09:08:23 -04004801 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4802 final String testPackage = "testPackageName";
4803 assertEquals(0, mService.mToastQueue.size());
4804 mService.isSystemUid = false;
4805
4806 // package is suspended
4807 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4808 .thenReturn(true);
4809
4810 // notifications from this package are NOT blocked by the user
4811 mService.setPreferencesHelper(mPreferencesHelper);
4812 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4813
4814 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004815 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004816 new TestableToastCallback(), 2000, 0);
4817 assertEquals(0, mService.mToastQueue.size());
4818 }
4819
4820 @Test
4821 public void testDisallowToastsFromBlockedApps() throws Exception {
4822 final String testPackage = "testPackageName";
4823 assertEquals(0, mService.mToastQueue.size());
4824 mService.isSystemUid = false;
4825
4826 // package is not suspended
4827 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4828 .thenReturn(false);
4829
4830 // notifications from this package are blocked by the user
4831 mService.setPreferencesHelper(mPreferencesHelper);
4832 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4833
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004834 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04004835
4836 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004837 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004838 new TestableToastCallback(), 2000, 0);
4839 assertEquals(0, mService.mToastQueue.size());
4840 }
4841
4842 @Test
4843 public void testAlwaysAllowSystemToasts() throws Exception {
4844 final String testPackage = "testPackageName";
4845 assertEquals(0, mService.mToastQueue.size());
4846 mService.isSystemUid = true;
4847
4848 // package is suspended
4849 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4850 .thenReturn(true);
4851
4852 // notifications from this package ARE blocked by the user
4853 mService.setPreferencesHelper(mPreferencesHelper);
4854 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4855
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004856 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04004857
4858 // enqueue toast -> system toast can still be enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004859 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004860 new TestableToastCallback(), 2000, 0);
4861 assertEquals(1, mService.mToastQueue.size());
4862 }
Tony Mak29996702018-11-26 16:23:34 +00004863
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004864 private void setAppInForegroundForToasts(int uid, boolean inForeground) {
4865 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
4866 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
4867 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
4868 }
4869
Tony Mak29996702018-11-26 16:23:34 +00004870 @Test
Alex Mang509e5542020-01-03 13:06:40 -08004871 public void testOnPanelRevealedAndHidden() {
4872 int items = 5;
4873 mService.mNotificationDelegate.onPanelRevealed(false, items);
4874 verify(mAssistants, times(1)).onPanelRevealed(eq(items));
4875
4876 mService.mNotificationDelegate.onPanelHidden();
4877 verify(mAssistants, times(1)).onPanelHidden();
Will Brockman9918db92020-03-06 16:48:39 -05004878
4879 assertEquals(2, mNotificationRecordLogger.numCalls());
4880 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
4881 mNotificationRecordLogger.event(0));
4882 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
4883 mNotificationRecordLogger.event(1));
Alex Mang509e5542020-01-03 13:06:40 -08004884 }
4885
4886 @Test
Tony Mak29996702018-11-26 16:23:34 +00004887 public void testOnNotificationSmartReplySent() {
4888 final int replyIndex = 2;
4889 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004890 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004891 final boolean generatedByAssistant = true;
4892
4893 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004894 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004895 mService.addNotification(r);
4896
4897 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004898 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4899 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004900 verify(mAssistants).notifyAssistantSuggestedReplySent(
Julia Reynolds24edc002020-01-29 16:35:32 -05004901 eq(r.getSbn()), eq(reply), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05004902 assertEquals(1, mNotificationRecordLogger.numCalls());
4903 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
4904 mNotificationRecordLogger.event(0));
Tony Mak29996702018-11-26 16:23:34 +00004905 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004906
4907 @Test
4908 public void testOnNotificationActionClick() {
4909 final int actionIndex = 2;
4910 final Notification.Action action =
4911 new Notification.Action.Builder(null, "text", null).build();
4912 final boolean generatedByAssistant = false;
4913
4914 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4915 mService.addNotification(r);
4916
4917 NotificationVisibility notificationVisibility =
4918 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4919 mService.mNotificationDelegate.onNotificationActionClick(
4920 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4921 generatedByAssistant);
4922 verify(mAssistants).notifyAssistantActionClicked(
Julia Reynolds24edc002020-01-29 16:35:32 -05004923 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05004924
4925 assertEquals(1, mNotificationRecordLogger.numCalls());
4926 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED,
4927 mNotificationRecordLogger.event(0));
Tony Mak7d4b3a52018-11-27 17:29:36 +00004928 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004929
4930 @Test
4931 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4932 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4933 mService.addNotification(r);
4934
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004935 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4936 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004937 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4938 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4939 };
4940 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4941 new NotificationVisibility[0]);
4942
4943 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4944 }
4945
4946 @Test
4947 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4948 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4949 mService.addNotification(r);
4950
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004951 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4952 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004953
4954 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4955 }
4956
4957 @Test
4958 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4959 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4960 mService.addNotification(r);
4961
Julia Reynolds95334132018-12-19 11:15:35 -05004962 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004963 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4964 };
4965 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4966 new NotificationVisibility[0]);
4967
4968 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4969 }
Julia Reynolds95334132018-12-19 11:15:35 -05004970
Colin Cross5ea7fb72019-12-18 17:16:36 -08004971 @Test
Julia Reynolds95334132018-12-19 11:15:35 -05004972 public void testReportSeen_delegated() {
4973 Notification.Builder nb =
4974 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4975 .setContentTitle("foo")
4976 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4977
4978 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4979 nb.build(), new UserHandle(mUid), null, 0);
4980 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4981
4982 mService.reportSeen(r);
4983 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4984
4985 }
4986
4987 @Test
4988 public void testReportSeen_notDelegated() {
4989 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4990
4991 mService.reportSeen(r);
4992 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4993 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004994
4995 @Test
4996 public void testNotificationStats_notificationError() {
4997 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4998 mService.addNotification(r);
4999
Julia Reynolds24edc002020-01-29 16:35:32 -05005000 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
5001 r.getSbn().getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005002 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
5003 new UserHandle(mUid), null, 0);
5004 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5005 mService.addEnqueuedNotification(update);
Julia Reynolds24edc002020-01-29 16:35:32 -05005006 assertNull(update.getSbn().getNotification().getSmallIcon());
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005007
5008 NotificationManagerService.PostNotificationRunnable runnable =
5009 mService.new PostNotificationRunnable(update.getKey());
5010 runnable.run();
5011 waitForIdle();
5012
5013 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
5014 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
5015 assertNotNull(captor.getValue());
5016 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005017
5018 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005019 public void testCanNotifyAsUser_crossUser() throws Exception {
5020 // same user no problem
5021 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
5022
5023 // cross user, no permission, problem
5024 try {
5025 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5026 fail("Should not be callable cross user without cross user permission");
5027 } catch (SecurityException e) {
5028 // good
5029 }
5030
5031 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005032 enableInteractAcrossUsers();
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005033 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5034 }
5035
5036 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005037 public void testgetNotificationChannels_crossUser() throws Exception {
5038 // same user no problem
5039 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
5040
5041 // cross user, no permission, problem
5042 try {
5043 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5044 fail("Should not be callable cross user without cross user permission");
5045 } catch (SecurityException e) {
5046 // good
5047 }
5048
5049 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005050 enableInteractAcrossUsers();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005051 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5052 }
5053
5054 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00005055 public void setDefaultAssistantForUser_fromConfigXml() {
5056 clearDeviceConfig();
5057 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04005058 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005059 when(mResources
5060 .getString(
5061 com.android.internal.R.string.config_defaultAssistantAccessComponent))
5062 .thenReturn(xmlConfig.flattenToString());
5063 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005064 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
5065 .thenReturn(components);
5066 when(mAssistants.getDefaultComponents())
5067 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00005068 mService.setNotificationAssistantAccessGrantedCallback(
5069 mNotificationAssistantAccessGrantedCallback);
5070
Jay Aliomer4204f252019-08-26 11:36:53 -04005071
Tony Mak9a3c1f12019-03-04 16:04:42 +00005072 mService.setDefaultAssistantForUser(0);
5073
5074 verify(mNotificationAssistantAccessGrantedCallback)
5075 .onGranted(eq(xmlConfig), eq(0), eq(true));
5076 }
5077
5078 @Test
5079 public void setDefaultAssistantForUser_fromDeviceConfig() {
5080 ComponentName xmlConfig = new ComponentName("xml", "config");
5081 ComponentName deviceConfig = new ComponentName("device", "config");
5082 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5083 when(mResources
5084 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5085 .thenReturn(xmlConfig.flattenToString());
5086 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005087 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00005088 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04005089 when(mAssistants.getDefaultComponents())
5090 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005091 mService.setNotificationAssistantAccessGrantedCallback(
5092 mNotificationAssistantAccessGrantedCallback);
5093
5094 mService.setDefaultAssistantForUser(0);
5095
5096 verify(mNotificationAssistantAccessGrantedCallback)
5097 .onGranted(eq(deviceConfig), eq(0), eq(true));
5098 }
5099
5100 @Test
5101 public void setDefaultAssistantForUser_deviceConfigInvalid() {
5102 ComponentName xmlConfig = new ComponentName("xml", "config");
5103 ComponentName deviceConfig = new ComponentName("device", "config");
5104 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5105 when(mResources
5106 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5107 .thenReturn(xmlConfig.flattenToString());
5108 when(mContext.getResources()).thenReturn(mResources);
5109 // Only xmlConfig is valid, deviceConfig is not.
5110 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04005111 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
5112 when(mAssistants.getDefaultComponents())
5113 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005114 mService.setNotificationAssistantAccessGrantedCallback(
5115 mNotificationAssistantAccessGrantedCallback);
5116
5117 mService.setDefaultAssistantForUser(0);
5118
5119 verify(mNotificationAssistantAccessGrantedCallback)
5120 .onGranted(eq(xmlConfig), eq(0), eq(true));
5121 }
5122
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005123 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04005124 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
5125 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
5126 generateResetComponentValues();
5127 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
5128 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5129 ComponentName deviceConfig1 = new ComponentName("device", "config1");
5130 ComponentName deviceConfig2 = new ComponentName("device", "config2");
5131 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
5132 changes.put(false, new ArrayList());
5133 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
5134 mService.getBinderService().clearData("device", 0, false);
5135 verify(mAssistants, times(1))
5136 .setPackageOrComponentEnabled(
5137 eq("device/config2"),
5138 eq(0), eq(true), eq(false));
5139 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5140 eq("device"), eq(0), eq(false), eq(true));
5141 }
5142
5143 @Test
5144 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
5145 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
5146 generateResetComponentValues();
5147 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
5148 ComponentName deviceConfig = new ComponentName("device", "config");
5149 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5150 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
5151 changes.put(false, new ArrayList());
5152 when(mListeners.resetComponents(anyString(), anyInt()))
5153 .thenReturn(changes);
5154 mService.getBinderService().clearData("device", 0, false);
5155 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5156 eq("device"), eq(0), eq(false), eq(true));
5157 }
5158
5159 @Test
5160 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
5161 ComponentName deviceConfig = new ComponentName("device", "config");
5162 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
5163 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
5164 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
5165 mService.getBinderService().clearData("device", 0, false);
5166 verify(mConditionProviders, times(1)).resetPackage(
5167 eq("device"), eq(0));
5168 }
5169
5170 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07005171 public void testFlagBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005172 setUpPrefsForBubbles(PKG, mUid,
5173 true /* global */,
5174 BUBBLE_PREFERENCE_ALL /* app */,
5175 true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07005176
Mady Mellor9e923e12019-12-17 16:08:46 -08005177 NotificationRecord nr =
5178 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
Mady Mellor65dcaa92019-04-03 12:21:44 -07005179
Julia Reynolds24edc002020-01-29 16:35:32 -05005180 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5181 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005182 waitForIdle();
5183
5184 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5185 assertEquals(1, notifs.length);
5186 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
5187 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005188 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005189 }
5190
5191 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07005192 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005193 setUpPrefsForBubbles(PKG, mUid,
5194 true /* global */,
5195 BUBBLE_PREFERENCE_NONE /* app */,
5196 true /* channel */);
Mady Mellorc6820342019-05-20 12:04:36 -07005197
Mady Mellor9e923e12019-12-17 16:08:46 -08005198 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5199 "testFlagBubble_noFlag_appNotAllowed");
Mady Mellorc6820342019-05-20 12:04:36 -07005200
Julia Reynolds24edc002020-01-29 16:35:32 -05005201 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5202 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorc6820342019-05-20 12:04:36 -07005203 waitForIdle();
5204
5205 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5206 assertEquals(1, notifs.length);
5207 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
5208 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005209 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorc6820342019-05-20 12:04:36 -07005210 }
5211
5212 @Test
Mady Mellor9e923e12019-12-17 16:08:46 -08005213 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005214 setUpPrefsForBubbles(PKG, mUid,
5215 true /* global */,
5216 BUBBLE_PREFERENCE_ALL /* app */,
5217 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005218
Mady Mellorbe797962019-04-01 16:04:24 -07005219 // Notif with bubble metadata but not our other misc requirements
Mady Mellor9e923e12019-12-17 16:08:46 -08005220 Notification.Builder nb = new Notification.Builder(mContext,
5221 mTestNotificationChannel.getId())
5222 .setContentTitle("foo")
5223 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Mady Mellora92268c2020-03-09 17:25:08 -07005224 .setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -08005225 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
5226 nb.build(), new UserHandle(mUid), null, 0);
5227 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellorbe797962019-04-01 16:04:24 -07005228
5229 // Say we're foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05005230 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellorbe797962019-04-01 16:04:24 -07005231 IMPORTANCE_FOREGROUND);
Julia Reynolds24edc002020-01-29 16:35:32 -05005232 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5233 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005234 waitForIdle();
5235
Mady Mellor9e923e12019-12-17 16:08:46 -08005236 // if notif isn't configured properly it doesn't get to bubble just because app is
5237 // foreground.
Mady Mellorbe797962019-04-01 16:04:24 -07005238 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005239 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005240 }
5241
5242 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005243 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005244 setUpPrefsForBubbles(PKG, mUid,
5245 true /* global */,
5246 BUBBLE_PREFERENCE_ALL /* app */,
5247 true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005248
Mady Mellor9e923e12019-12-17 16:08:46 -08005249 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5250 "testFlagBubbleNotifs_flag_messaging");
Mady Mellorbe797962019-04-01 16:04:24 -07005251
Julia Reynolds24edc002020-01-29 16:35:32 -05005252 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5253 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005254 waitForIdle();
5255
5256 // yes allowed, yes messaging, yes bubble
5257 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005258 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005259 }
5260
5261 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005262 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005263 setUpPrefsForBubbles(PKG, mUid,
5264 true /* global */,
5265 BUBBLE_PREFERENCE_NONE /* app */,
5266 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005267
Mady Mellor9e923e12019-12-17 16:08:46 -08005268 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5269 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005270
5271 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005272 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5273 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005274 waitForIdle();
5275
5276 // not allowed, no bubble
5277 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005278 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005279 }
5280
5281 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005282 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005283 setUpPrefsForBubbles(PKG, mUid,
5284 true /* global */,
5285 BUBBLE_PREFERENCE_ALL /* app */,
5286 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005287
Mady Mellor9e923e12019-12-17 16:08:46 -08005288 // Messaging notif WITHOUT bubble metadata
5289 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
5290 null /* groupKey */, false /* isSummary */);
5291
5292 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5293 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
5294 nb.build(), new UserHandle(mUid), null, 0);
5295 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005296
5297 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005298 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5299 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005300 waitForIdle();
5301
5302 // no bubble metadata, no bubble
5303 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005304 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005305 }
5306
5307 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005308 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005309 setUpPrefsForBubbles(PKG, mUid,
5310 true /* global */,
5311 BUBBLE_PREFERENCE_ALL /* app */,
5312 false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005313
Mady Mellor9e923e12019-12-17 16:08:46 -08005314 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5315 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
Mady Mellora92268c2020-03-09 17:25:08 -07005316 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005317
5318 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005319 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5320 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005321 waitForIdle();
5322
5323 // channel not allowed, no bubble
5324 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005325 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005326 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005327
Mady Mellor49b1bf12019-03-29 12:00:02 -07005328 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005329 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
Mady Mellor49b1bf12019-03-29 12:00:02 -07005330 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005331 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005332
5333 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005334 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5335 "testAppCancelNotifications_cancelsBubbles",
Julia Reynolds24edc002020-01-29 16:35:32 -05005336 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
5337 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005338 waitForIdle();
5339
5340 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5341 assertEquals(1, notifs.length);
5342 assertEquals(1, mService.getNotificationRecordCount());
5343
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005344 mBinderService.cancelNotificationWithTag(PKG, PKG,
Julia Reynolds24edc002020-01-29 16:35:32 -05005345 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
5346 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005347 waitForIdle();
5348
5349 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5350 assertEquals(0, notifs2.length);
5351 assertEquals(0, mService.getNotificationRecordCount());
5352 }
5353
5354 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005355 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
5356 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5357 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5358 mService.addNotification(nr);
5359
5360 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
5361 waitForIdle();
5362
5363 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5364 assertEquals(0, notifs.length);
5365 assertEquals(0, mService.getNotificationRecordCount());
5366 }
5367
5368 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005369 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5370 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5371 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005372 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005373
5374 mService.addNotification(nrNormal);
5375 mService.addNotification(nrBubble);
5376
5377 mService.getBinderService().cancelNotificationsFromListener(null, null);
5378 waitForIdle();
5379
5380 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5381 assertEquals(1, notifs.length);
5382 assertEquals(1, mService.getNotificationRecordCount());
5383 }
5384
5385 @Test
5386 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
5387 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5388 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005389 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005390
5391 mService.addNotification(nrNormal);
5392 mService.addNotification(nrBubble);
5393
Julia Reynolds24edc002020-01-29 16:35:32 -05005394 String[] keys = {nrNormal.getSbn().getKey(), nrBubble.getSbn().getKey()};
Mady Mellor49b1bf12019-03-29 12:00:02 -07005395 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5396 waitForIdle();
5397
5398 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5399 assertEquals(1, notifs.length);
5400 assertEquals(1, mService.getNotificationRecordCount());
Will Brockman9918db92020-03-06 16:48:39 -05005401
5402 assertEquals(1, mNotificationRecordLogger.numCalls());
5403 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
5404 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
Mady Mellor49b1bf12019-03-29 12:00:02 -07005405 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005406
Julia Reynolds4214da92019-04-10 15:04:06 -04005407 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005408 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
5409 // GIVEN a notification bubble
5410 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5411 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5412 mService.addNotification(nr);
5413
5414 // WHEN the status bar clears all notifications
5415 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
5416 nr.getSbn().getUserId());
5417 waitForIdle();
5418
5419 // THEN the bubble notification does not get removed
5420 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5421 assertEquals(1, notifs.length);
5422 assertEquals(1, mService.getNotificationRecordCount());
5423 }
5424
5425
5426 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005427 public void testGetAllowedAssistantAdjustments() throws Exception {
5428 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005429 assertNotNull(capabilities);
5430
5431 for (int i = capabilities.size() - 1; i >= 0; i--) {
5432 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005433 mBinderService.disallowAssistantAdjustment(capability);
5434 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5435 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005436 assertNotNull(currentCapabilities);
5437 assertFalse(currentCapabilities.contains(capability));
5438 }
5439 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005440
Julia Reynolds4214da92019-04-10 15:04:06 -04005441 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005442 public void testAdjustRestrictedKey() throws Exception {
5443 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005444 mService.addNotification(r);
5445 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005446
5447 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5448 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5449
5450 Bundle signals = new Bundle();
5451 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5452 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
Julia Reynolds24edc002020-01-29 16:35:32 -05005453 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005454 "", r.getUser().getIdentifier());
5455
5456 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5457 r.applyAdjustments();
5458
5459 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5460 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5461 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005462
Julia Reynolds4214da92019-04-10 15:04:06 -04005463 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005464 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005465 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5466 .thenReturn(true);
5467 mService.setZenHelper(mock(ZenModeHelper.class));
5468 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005469 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5470 boolean isEnabled = true;
5471 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5472 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5473
5474 try {
5475 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005476 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005477 } catch (IllegalArgumentException e) {
5478 // yay
5479 }
5480
5481 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5482 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5483 mBinderService.addAutomaticZenRule(rule);
5484
5485 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5486 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5487 mBinderService.addAutomaticZenRule(rule);
5488 }
5489
Julia Reynolds4214da92019-04-10 15:04:06 -04005490 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005491 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5492 try {
5493 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5494 mUid + UserHandle.PER_USER_RANGE);
5495 fail("Cannot call cross user without permission");
5496 } catch (SecurityException e) {
5497 // pass
5498 }
5499
5500 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005501 enableInteractAcrossUsers();
Julia Reynolds657d1642019-03-27 12:15:57 -04005502 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5503 mUid + UserHandle.PER_USER_RANGE);
5504 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005505
Julia Reynolds4214da92019-04-10 15:04:06 -04005506 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005507 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5508 try {
Mady Mellora92268c2020-03-09 17:25:08 -07005509 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005510 mUid + UserHandle.PER_USER_RANGE);
5511 fail("Cannot call cross user without permission");
5512 } catch (SecurityException e) {
5513 // pass
5514 }
5515
5516 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005517 enableInteractAcrossUsers();
Mady Mellora92268c2020-03-09 17:25:08 -07005518 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005519 mUid + UserHandle.PER_USER_RANGE);
5520 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005521
Will Brockmancfd98302020-01-29 15:57:30 -05005522 private void enableInteractAcrossUsers() {
5523 TestablePermissions perms = mContext.getTestablePermissions();
5524 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5525 }
5526
Mady Mellora54e9fa2019-04-18 13:26:18 -07005527 @Test
5528 public void testNotificationBubbleChanged_false() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005529 setUpPrefsForBubbles(PKG, mUid,
5530 true /* global */,
5531 BUBBLE_PREFERENCE_ALL /* app */,
5532 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005533
Mady Mellor9e923e12019-12-17 16:08:46 -08005534 // Notif with bubble metadata
5535 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5536 "testNotificationBubbleChanged_false");
Mady Mellora54e9fa2019-04-18 13:26:18 -07005537
Julia Reynolds24edc002020-01-29 16:35:32 -05005538 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5539 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005540 waitForIdle();
5541
Mady Mellor66efd5e2019-05-15 13:38:11 -07005542 // Reset as this is called when the notif is first sent
5543 reset(mListeners);
5544
Mady Mellora54e9fa2019-04-18 13:26:18 -07005545 // First we were a bubble
5546 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5547 assertEquals(1, notifsBefore.length);
5548 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5549
5550 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005551 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005552 waitForIdle();
5553
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005554 // Make sure we are not a bubble
5555 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5556 assertEquals(1, notifsAfter.length);
5557 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005558 }
5559
5560 @Test
5561 public void testNotificationBubbleChanged_true() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005562 setUpPrefsForBubbles(PKG, mUid,
5563 true /* global */,
5564 BUBBLE_PREFERENCE_ALL /* app */,
5565 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005566
Mady Mellor9e923e12019-12-17 16:08:46 -08005567 // Notif that is not a bubble
Mady Mellora54e9fa2019-04-18 13:26:18 -07005568 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08005569 1, null, false);
Julia Reynolds24edc002020-01-29 16:35:32 -05005570 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5571 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005572 waitForIdle();
5573
5574 // Would be a normal notification because wouldn't have met requirements to bubble
5575 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5576 assertEquals(1, notifsBefore.length);
5577 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5578
Mady Mellor9e923e12019-12-17 16:08:46 -08005579 // Update the notification to be message style / meet bubble requirements
5580 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
Julia Reynolds24edc002020-01-29 16:35:32 -05005581 nr.getSbn().getTag());
5582 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
5583 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
Mady Mellor9e923e12019-12-17 16:08:46 -08005584 waitForIdle();
Mady Mellora54e9fa2019-04-18 13:26:18 -07005585
Mady Mellor66efd5e2019-05-15 13:38:11 -07005586 // Reset as this is called when the notif is first sent
5587 reset(mListeners);
5588
Mady Mellora54e9fa2019-04-18 13:26:18 -07005589 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005590 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005591 waitForIdle();
5592
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005593 // Make sure we are a bubble
5594 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5595 assertEquals(1, notifsAfter.length);
5596 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005597 }
5598
5599 @Test
5600 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005601 setUpPrefsForBubbles(PKG, mUid,
5602 true /* global */,
5603 BUBBLE_PREFERENCE_ALL /* app */,
5604 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005605
5606 // Notif that is not a bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005607 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005608 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5609 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005610 waitForIdle();
5611
Mady Mellor66efd5e2019-05-15 13:38:11 -07005612 // Reset as this is called when the notif is first sent
5613 reset(mListeners);
5614
Mady Mellora54e9fa2019-04-18 13:26:18 -07005615 // Would be a normal notification because wouldn't have met requirements to bubble
5616 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5617 assertEquals(1, notifsBefore.length);
5618 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5619
5620 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005621 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005622 waitForIdle();
5623
5624 // We still wouldn't be a bubble because the notification didn't meet requirements
5625 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5626 assertEquals(1, notifsAfter.length);
5627 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5628 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005629
5630 @Test
Mady Mellor13f9bc82020-03-24 19:09:28 -07005631 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005632 setUpPrefsForBubbles(PKG, mUid,
5633 true /* global */,
5634 BUBBLE_PREFERENCE_ALL /* app */,
5635 true /* channel */);
5636
Mady Mellor13f9bc82020-03-24 19:09:28 -07005637 // Notif with bubble metadata
5638 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5639 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
5640
5641 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5642 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5643 waitForIdle();
5644 // Flag shouldn't be modified
5645 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5646 assertFalse(recordToCheck.isFlagBubbleRemoved());
5647
5648 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005649 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005650 waitForIdle();
5651 // Flag should be modified
5652 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5653 assertTrue(recordToCheck.isFlagBubbleRemoved());
5654
5655
5656 // Update the notif
5657 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5658 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5659 waitForIdle();
5660 // And the flag is reset
5661 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5662 assertFalse(recordToCheck.isFlagBubbleRemoved());
5663 }
5664
5665 @Test
5666 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005667 setUpPrefsForBubbles(PKG, mUid,
5668 true /* global */,
5669 BUBBLE_PREFERENCE_ALL /* app */,
5670 true /* channel */);
5671
Mady Mellor13f9bc82020-03-24 19:09:28 -07005672 // Notif with bubble metadata
5673 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5674 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
5675
5676 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5677 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5678 waitForIdle();
5679 // Flag shouldn't be modified
5680 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5681 assertFalse(recordToCheck.isFlagBubbleRemoved());
5682
5683 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005684 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005685 waitForIdle();
5686 // Flag should be modified
5687 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5688 assertTrue(recordToCheck.isFlagBubbleRemoved());
5689
5690 // Notify we are a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005691 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005692 waitForIdle();
5693 // And the flag is reset
5694 assertFalse(recordToCheck.isFlagBubbleRemoved());
5695 }
5696
5697 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -08005698 public void testOnBubbleNotificationSuppressionChanged() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005699 setUpPrefsForBubbles(PKG, mUid,
5700 true /* global */,
5701 BUBBLE_PREFERENCE_ALL /* app */,
5702 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08005703
Mady Mellorf44b6832020-01-14 13:26:14 -08005704 // Bubble notification
5705 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5706
Julia Reynolds24edc002020-01-29 16:35:32 -05005707 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5708 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorf44b6832020-01-14 13:26:14 -08005709 waitForIdle();
5710
5711 // NOT suppressed
5712 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5713 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5714
5715 // Reset as this is called when the notif is first sent
5716 reset(mListeners);
5717
5718 // Test: update suppression to true
5719 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
5720 waitForIdle();
5721
5722 // Check
5723 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5724 assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
5725
5726 // Reset to check again
5727 reset(mListeners);
5728
5729 // Test: update suppression to false
5730 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
5731 waitForIdle();
5732
5733 // Check
5734 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5735 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5736 }
5737
5738 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005739 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
5740 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5741 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005742 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005743 waitForIdle();
5744
5745 // A notification exists for the given record
5746 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5747 assertEquals(1, notifsBefore.length);
5748
5749 reset(mPackageManager);
5750
5751 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5752
5753 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005754 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5755 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005756
5757 // Grant permission called for the UID of SystemUI under the target user ID
5758 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005759 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5760 anyInt(), eq(nr.getSbn().getUserId()));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005761 }
5762
5763 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005764 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
5765 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5766 waitForIdle();
5767
5768 // No notifications exist for the given record
5769 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5770 assertEquals(0, notifsBefore.length);
5771
5772 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5773 int uid = 0; // sysui on primary user
5774
5775 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005776 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5777 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005778
5779 // Grant permission still called if no NotificationRecord exists for the given key
5780 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005781 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5782 anyInt(), eq(nr.getSbn().getUserId()));
Aran Ink979c9762019-10-24 16:09:45 -04005783 }
5784
5785 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005786 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
5787 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5788 NotificationRecord nr =
5789 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
5790 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005791 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005792 waitForIdle();
5793
5794 // A notification exists for the given record
5795 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5796 assertEquals(1, notifsBefore.length);
5797
5798 reset(mPackageManager);
5799
5800 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5801
5802 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005803 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5804 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005805
5806 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5807 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005808 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5809 anyInt(), eq(UserHandle.USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005810 }
5811
5812 @Test
5813 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
5814 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5815 int otherUserId = 11;
5816 NotificationRecord nr =
5817 generateNotificationRecord(mTestNotificationChannel, otherUserId);
5818 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005819 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005820 waitForIdle();
5821
5822 // A notification exists for the given record
5823 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5824 assertEquals(1, notifsBefore.length);
5825
5826 reset(mPackageManager);
5827
5828 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5829
5830 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04005831 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04005832 String sysuiPackage = "sysui";
5833 final String[] sysuiPackages = new String[] { sysuiPackage };
5834 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
5835
5836 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
5837 // time this is called
5838 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
5839 .thenReturn(otherUserUid);
5840
Aran Ink979c9762019-10-24 16:09:45 -04005841 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005842 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005843
5844 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5845 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005846 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
Aran Inkfd2bfd32019-10-04 16:30:01 -04005847 eq(otherUserId));
5848 }
5849
5850 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005851 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
5852 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5853 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005854
Aran Ink979c9762019-10-24 16:09:45 -04005855 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5856 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005857
Aran Ink979c9762019-10-24 16:09:45 -04005858 // create an inline record with two uris in it
5859 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005860 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5861 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005862 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005863 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5864 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005865
Aran Ink979c9762019-10-24 16:09:45 -04005866 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5867 assertNotNull(record); // record exists
5868 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04005869
Julia Reynolds24edc002020-01-29 16:35:32 -05005870 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
5871 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005872
5873 // permissionOwner destroyed
5874 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5875 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
5876 }
5877
5878
5879 @Test
5880 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
5881 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5882 reset(mPackageManager);
5883
Julia Reynolds24edc002020-01-29 16:35:32 -05005884 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
5885 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005886
5887 // no permissionOwner destroyed
5888 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
5889 any(), eq(null), eq(~0), eq(nr.getUserId()));
5890 }
5891
5892 @Test
5893 public void testClearInlineReplyUriPermission_userAll() throws Exception {
5894 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5895 UserHandle.USER_ALL);
5896 reset(mPackageManager);
5897
5898 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5899 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
5900
5901 // create an inline record a uri in it
5902 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005903 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5904 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005905
5906 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5907 assertNotNull(record); // record exists
5908
Julia Reynolds24edc002020-01-29 16:35:32 -05005909 mService.mNotificationDelegate.clearInlineReplyUriPermissions(
5910 nr.getKey(), nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005911
5912 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
5913 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5914 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005915 }
5916
5917 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005918 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005919 setUpPrefsForBubbles(PKG, mUid,
5920 true /* global */,
5921 BUBBLE_PREFERENCE_ALL /* app */,
5922 true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005923
Mady Mellor9e923e12019-12-17 16:08:46 -08005924 // And we are low ram
5925 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5926
5927 // Notification that would typically bubble
5928 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5929 "testNotificationBubbles_disabled_lowRamDevice");
Julia Reynolds24edc002020-01-29 16:35:32 -05005930 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5931 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005932 waitForIdle();
5933
Mady Mellor9e923e12019-12-17 16:08:46 -08005934 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005935 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5936 assertEquals(1, notifsAfter.length);
5937 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005938 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04005939
5940 @Test
5941 public void testRemoveLargeRemoteViews() throws Exception {
5942 int removeSize = mContext.getResources().getInteger(
5943 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
5944
5945 RemoteViews rv = mock(RemoteViews.class);
5946 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
5947 when(rv.clone()).thenReturn(rv);
5948 RemoteViews rv1 = mock(RemoteViews.class);
5949 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
5950 when(rv1.clone()).thenReturn(rv1);
5951 RemoteViews rv2 = mock(RemoteViews.class);
5952 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
5953 when(rv2.clone()).thenReturn(rv2);
5954 RemoteViews rv3 = mock(RemoteViews.class);
5955 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
5956 when(rv3.clone()).thenReturn(rv3);
5957 RemoteViews rv4 = mock(RemoteViews.class);
5958 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
5959 when(rv4.clone()).thenReturn(rv4);
5960 // note: different!
5961 RemoteViews rv5 = mock(RemoteViews.class);
5962 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
5963 when(rv5.clone()).thenReturn(rv5);
5964
5965 Notification np = new Notification.Builder(mContext, "test")
5966 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5967 .setContentText("test")
5968 .setCustomContentView(rv)
5969 .setCustomBigContentView(rv1)
5970 .setCustomHeadsUpContentView(rv2)
5971 .build();
5972 Notification n = new Notification.Builder(mContext, "test")
5973 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5974 .setContentText("test")
5975 .setCustomContentView(rv3)
5976 .setCustomBigContentView(rv4)
5977 .setCustomHeadsUpContentView(rv5)
5978 .setPublicVersion(np)
5979 .build();
5980
5981 assertNotNull(np.contentView);
5982 assertNotNull(np.bigContentView);
5983 assertNotNull(np.headsUpContentView);
5984
5985 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
5986 assertNotNull(n.publicVersion.contentView);
5987 assertNotNull(n.publicVersion.bigContentView);
5988 assertNotNull(n.publicVersion.headsUpContentView);
5989
5990 mService.fixNotification(n, PKG, "tag", 9, 0);
5991
5992 assertNull(n.contentView);
5993 assertNull(n.bigContentView);
5994 assertNotNull(n.headsUpContentView);
5995 assertNull(n.publicVersion.contentView);
5996 assertNull(n.publicVersion.bigContentView);
5997 assertNull(n.publicVersion.headsUpContentView);
5998
5999 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
6000 }
Mady Mellor06b770c2019-08-29 18:01:00 -07006001
Colin Cross5ea7fb72019-12-18 17:16:36 -08006002 @Test
Mady Mellora7731962019-06-17 17:57:02 -07006003 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
6004 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006005 setUpPrefsForBubbles(PKG, mUid,
6006 true /* global */,
6007 BUBBLE_PREFERENCE_ALL /* app */,
6008 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006009
Mady Mellor9e923e12019-12-17 16:08:46 -08006010 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6011 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
6012 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006013 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006014 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6015 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006016
6017 // Ensure we're not foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006018 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006019 IMPORTANCE_VISIBLE);
6020
Julia Reynolds24edc002020-01-29 16:35:32 -05006021 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6022 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006023 waitForIdle();
6024
6025 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006026 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006027 assertTrue(notif.isBubbleNotification());
6028
6029 // Our flags should have failed since we're not foreground
6030 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
6031 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
6032 }
6033
6034 @Test
6035 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
6036 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006037 setUpPrefsForBubbles(PKG, mUid,
6038 true /* global */,
6039 BUBBLE_PREFERENCE_ALL /* app */,
6040 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006041
Mady Mellor9e923e12019-12-17 16:08:46 -08006042 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6043 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
6044 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006045 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006046 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6047 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006048
6049 // Ensure we are in the foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006050 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006051 IMPORTANCE_FOREGROUND);
6052
Julia Reynolds24edc002020-01-29 16:35:32 -05006053 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6054 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006055 waitForIdle();
6056
6057 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006058 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006059 assertTrue(notif.isBubbleNotification());
6060
Mady Mellor9e923e12019-12-17 16:08:46 -08006061 // Our flags should have passed since we are foreground
Mady Mellora7731962019-06-17 17:57:02 -07006062 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
6063 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
6064 }
Mady Mellor22f2f072019-04-18 13:26:18 -07006065
6066 @Test
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006067 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
6068 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006069 setUpPrefsForBubbles(PKG, mUid,
6070 true /* global */,
6071 BUBBLE_PREFERENCE_ALL /* app */,
6072 true /* channel */);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006073
6074 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6075 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6076
6077 // Messaging notification with shortcut info
6078 Notification.BubbleMetadata metadata =
Mady Melloraa9ce172020-03-17 10:34:20 -07006079 new Notification.BubbleMetadata.Builder("someshortcutId").build();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006080 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6081 null /* groupKey */, false /* isSummary */);
6082 nb.setBubbleMetadata(metadata);
6083 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6084 "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
6085 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6086
6087 // Pretend the shortcut exists
6088 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
Julia Reynoldsd61bdf12020-02-25 12:25:07 -05006089 ShortcutInfo info = mock(ShortcutInfo.class);
6090 when(info.isLongLived()).thenReturn(true);
6091 shortcutInfos.add(info);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006092 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
6093
6094 // Test: Send the bubble notification
Julia Reynolds24edc002020-01-29 16:35:32 -05006095 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6096 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006097 waitForIdle();
6098
6099 // Verify:
6100
6101 // Make sure we register the callback for shortcut changes
6102 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6103
6104 // yes allowed, yes messaging w/shortcut, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006105 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006106 assertTrue(notif.isBubbleNotification());
6107
6108 // Test: Remove the shortcut
Mady Mellor56515c42020-02-18 17:58:36 -08006109 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006110 launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
6111 new UserHandle(mUid));
Mady Mellor56515c42020-02-18 17:58:36 -08006112 waitForIdle();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006113
6114 // Verify:
6115
6116 // Make sure callback is unregistered
6117 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6118
6119 // We're no longer a bubble
Julia Reynoldsd61bdf12020-02-25 12:25:07 -05006120 Notification notif2 = mService.getNotificationRecord(
6121 nr.getSbn().getKey()).getNotification();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006122 assertFalse(notif2.isBubbleNotification());
6123 }
6124
Mady Mellor56515c42020-02-18 17:58:36 -08006125
6126 @Test
6127 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
6128 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006129 setUpPrefsForBubbles(PKG, mUid,
6130 true /* global */,
6131 BUBBLE_PREFERENCE_ALL /* app */,
6132 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08006133
6134 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6135 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6136
6137 // Messaging notification with shortcut info
Mady Melloraa9ce172020-03-17 10:34:20 -07006138 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
6139 "someshortcutId").build();
Mady Mellor56515c42020-02-18 17:58:36 -08006140 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6141 null /* groupKey */, false /* isSummary */);
6142 nb.setBubbleMetadata(metadata);
6143 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6144 "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
6145 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6146
6147 // Pretend the shortcut exists
6148 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
6149 ShortcutInfo info = mock(ShortcutInfo.class);
6150 when(info.isLongLived()).thenReturn(true);
6151 shortcutInfos.add(info);
6152 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
6153
6154 // Test: Send the bubble notification
6155 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6156 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6157 waitForIdle();
6158
6159 // Verify:
6160
6161 // Make sure we register the callback for shortcut changes
6162 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6163
6164 // yes allowed, yes messaging w/shortcut, yes bubble
6165 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6166 assertTrue(notif.isBubbleNotification());
6167
6168 // Test: Remove the notification
6169 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6170 nr.getSbn().getId(), nr.getSbn().getUserId());
6171 waitForIdle();
6172
6173 // Verify:
6174
6175 // Make sure callback is unregistered
6176 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6177 }
6178
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006179 @Test
Mady Mellor22f2f072019-04-18 13:26:18 -07006180 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
6181 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006182 setUpPrefsForBubbles(PKG, mUid,
6183 true /* global */,
6184 BUBBLE_PREFERENCE_ALL /* app */,
6185 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006186
6187 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6188 true /* summaryAutoCancel */);
6189
6190 // Dismiss summary
6191 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6192 true);
Julia Reynolds24edc002020-01-29 16:35:32 -05006193 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
6194 nrSummary.getSbn().getTag(),
6195 nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
Mady Mellor22f2f072019-04-18 13:26:18 -07006196 NotificationStats.DISMISSAL_SHADE,
6197 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
6198 waitForIdle();
6199
6200 // The bubble should still exist
6201 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6202 assertEquals(1, notifsAfter.length);
6203 }
6204
6205 @Test
6206 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
6207 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006208 setUpPrefsForBubbles(PKG, mUid,
6209 true /* global */,
6210 BUBBLE_PREFERENCE_ALL /* app */,
6211 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006212
6213 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6214 true /* summaryAutoCancel */);
6215
6216 // Click summary
6217 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6218 true);
6219 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6220 nrSummary.getKey(), nv);
6221 waitForIdle();
6222
6223 // The bubble should still exist
6224 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6225 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006226
6227 // Check we got the click log and associated dismissal logs
6228 assertEquals(6, mNotificationRecordLogger.numCalls());
6229 // Skip the notification-creation logs
6230 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6231 mNotificationRecordLogger.event(3));
6232 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
6233 mNotificationRecordLogger.event(4));
6234 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
6235 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
6236 mNotificationRecordLogger.event(5));
Mady Mellor22f2f072019-04-18 13:26:18 -07006237 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04006238
6239 @Test
Beverly9e6a7642020-02-13 10:11:29 -05006240 public void testNotificationBubbles_bubbleStays_whenClicked()
6241 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006242 setUpPrefsForBubbles(PKG, mUid,
6243 true /* global */,
6244 BUBBLE_PREFERENCE_ALL /* app */,
6245 true /* channel */);
6246
Beverly9e6a7642020-02-13 10:11:29 -05006247 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
Beverly9e6a7642020-02-13 10:11:29 -05006248 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
6249 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
6250 mService.addNotification(nr);
6251
6252 // WHEN we click the notification
6253 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
6254 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6255 nr.getKey(), nv);
6256 waitForIdle();
6257
6258 // THEN the bubble should still exist
6259 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6260 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006261
6262 // Check we got the click log
6263 assertEquals(1, mNotificationRecordLogger.numCalls());
6264 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6265 mNotificationRecordLogger.event(0));
Beverly9e6a7642020-02-13 10:11:29 -05006266 }
6267
6268 @Test
Julia Reynolds57a974b2019-10-07 11:51:47 -04006269 public void testLoadDefaultApprovedServices_emptyResources() {
6270 TestableResources tr = mContext.getOrCreateTestableResources();
6271 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
6272 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
6273 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
6274 setDefaultAssistantInDeviceConfig("");
6275
6276 mService.loadDefaultApprovedServices(USER_SYSTEM);
6277
6278 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
6279 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
6280 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
6281 }
6282
6283 @Test
6284 public void testLoadDefaultApprovedServices_dnd() {
6285 TestableResources tr = mContext.getOrCreateTestableResources();
6286 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
6287 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
6288 .thenReturn(new ArraySet<>());
6289
6290 mService.loadDefaultApprovedServices(USER_SYSTEM);
6291
6292 verify(mConditionProviders, times(1)).addDefaultComponentOrPackage("test");
6293 }
6294
6295 // TODO: add tests for the rest of the non-empty cases
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006296
6297 @Test
6298 public void testOnUnlockUser() {
6299 UserInfo ui = new UserInfo();
6300 ui.id = 10;
6301 mService.onUnlockUser(ui);
6302 waitForIdle();
6303
6304 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
6305 }
6306
6307 @Test
6308 public void testOnStopUser() {
6309 UserInfo ui = new UserInfo();
6310 ui.id = 10;
6311 mService.onStopUser(ui);
6312 waitForIdle();
6313
6314 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
6315 }
6316
6317 @Test
6318 public void testOnBootPhase() {
6319 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
6320
6321 verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
6322
6323 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
6324
6325 verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart();
6326 }
6327
6328 @Test
6329 public void testHandleOnPackageChanged() {
6330 String[] pkgs = new String[] {PKG, PKG_N_MR1};
6331 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
6332
6333 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
6334
6335 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
6336
6337 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
6338
6339 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
6340 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
6341 }
6342
6343 @Test
6344 public void testNotificationHistory_addNoisyNotification() throws Exception {
6345 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08006346 null /* tvExtender */);
Julia Reynolds24edc002020-01-29 16:35:32 -05006347 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6348 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006349 waitForIdle();
6350
6351 verify(mHistoryManager, times(1)).addNotification(any());
6352 }
Julia Reynolds0f767342019-12-18 09:11:55 -05006353
6354 @Test
6355 public void createConversationNotificationChannel() throws Exception {
6356 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
6357 original.setAllowBubbles(!original.canBubble());
6358 original.setShowBadge(!original.canShowBadge());
6359
6360 Parcel parcel = Parcel.obtain();
6361 original.writeToParcel(parcel, 0);
6362 parcel.setDataPosition(0);
6363 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
6364 assertEquals(original, orig);
6365 assertFalse(TextUtils.isEmpty(orig.getName()));
6366
6367 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6368 orig)));
6369
Julia Reynolds7c267522020-01-16 11:26:41 -05006370 mBinderService.createConversationNotificationChannelForPackage(
6371 PKG, mUid, "key", orig, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006372
6373 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006374 PKG, 0, PKG, original.getId(), false, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006375
6376 assertEquals(original.getName(), friendChannel.getName());
6377 assertEquals(original.getId(), friendChannel.getParentChannelId());
6378 assertEquals("friend", friendChannel.getConversationId());
6379 assertEquals(null, original.getConversationId());
6380 assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
Mady Mellora92268c2020-03-09 17:25:08 -07006381 assertFalse(friendChannel.canBubble()); // can't be modified by app
Julia Reynolds0f767342019-12-18 09:11:55 -05006382 assertFalse(original.getId().equals(friendChannel.getId()));
6383 assertNotNull(friendChannel.getId());
6384 }
6385
6386 @Test
6387 public void deleteConversationNotificationChannels() throws Exception {
6388 NotificationChannel messagesParent =
6389 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
6390 Parcel msgParcel = Parcel.obtain();
6391 messagesParent.writeToParcel(msgParcel, 0);
6392 msgParcel.setDataPosition(0);
6393
6394 NotificationChannel callsParent =
6395 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
6396 Parcel callParcel = Parcel.obtain();
6397 callsParent.writeToParcel(callParcel, 0);
6398 callParcel.setDataPosition(0);
6399
6400 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6401 messagesParent, callsParent)));
6402
6403 String conversationId = "friend";
6404
6405 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006406 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
6407 conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006408 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006409 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
Julia Reynolds0f767342019-12-18 09:11:55 -05006410 conversationId);
6411
6412 NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006413 PKG, 0, PKG, messagesParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006414 NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006415 PKG, 0, PKG, callsParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006416
6417 assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
6418 assertEquals(conversationId, messagesChild.getConversationId());
6419
6420 assertEquals(callsParent.getId(), callsChild.getParentChannelId());
6421 assertEquals(conversationId, callsChild.getConversationId());
6422
6423 mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
6424
6425 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006426 PKG, 0, PKG, messagesParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006427 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006428 PKG, 0, PKG, callsParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006429 }
Julia Reynolds24edc002020-01-29 16:35:32 -05006430
6431 @Test
6432 public void testCorrectCategory_systemOn_appCannotTurnOff() {
6433 int requested = 0;
6434 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6435
6436 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6437 system);
6438
6439 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
6440 }
6441
6442 @Test
6443 public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
6444 int requested = PRIORITY_CATEGORY_CALLS;
6445 int system = PRIORITY_CATEGORY_CALLS;
6446
6447 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6448 system);
6449
6450 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6451 }
6452
6453 @Test
6454 public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
6455 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6456 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6457
6458 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6459 system);
6460
6461 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
6462 }
6463
6464 @Test
6465 public void testCorrectCategory_systemOff_appCannotTurnOn() {
6466 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6467 int system = PRIORITY_CATEGORY_CALLS;
6468
6469 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6470 system);
6471
6472 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6473 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006474
6475 @Test
6476 public void testGetConversationsForPackage_hasShortcut() throws Exception {
6477 mService.setPreferencesHelper(mPreferencesHelper);
6478 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6479 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6480 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6481 channel1.setConversationId("parent1", "convo 1");
6482 convo1.setNotificationChannel(channel1);
6483 convos.add(convo1);
6484
6485 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6486 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6487 channel2.setConversationId("parent1", "convo 2");
6488 convo2.setNotificationChannel(channel2);
6489 convos.add(convo2);
6490 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6491
Julia Reynolds882f2062020-02-05 12:11:38 -05006492 ShortcutInfo si = mock(ShortcutInfo.class);
6493 when(si.getShortLabel()).thenReturn("Hello");
Mady Mellor774d5fe2020-03-05 11:35:03 -08006494 when(si.isLongLived()).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006495 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6496
6497 List<ConversationChannelWrapper> conversations =
6498 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6499 assertEquals(si, conversations.get(0).getShortcutInfo());
6500 assertEquals(si, conversations.get(1).getShortcutInfo());
Mady Mellor774d5fe2020-03-05 11:35:03 -08006501 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006502
Mady Mellor774d5fe2020-03-05 11:35:03 -08006503 @Test
6504 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
6505 mService.setPreferencesHelper(mPreferencesHelper);
6506 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6507 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6508 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6509 channel1.setConversationId("parent1", "convo 1");
6510 convo1.setNotificationChannel(channel1);
6511 convos.add(convo1);
6512
6513 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6514 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6515 channel2.setConversationId("parent1", "convo 2");
6516 convo2.setNotificationChannel(channel2);
6517 convos.add(convo2);
6518 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6519
6520 ShortcutInfo si = mock(ShortcutInfo.class);
6521 when(si.getShortLabel()).thenReturn("Hello");
6522 when(si.isLongLived()).thenReturn(false);
6523 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6524
6525 List<ConversationChannelWrapper> conversations =
6526 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6527 assertNull(conversations.get(0).getShortcutInfo());
6528 assertNull(conversations.get(1).getShortcutInfo());
Julia Reynolds882f2062020-02-05 12:11:38 -05006529 }
6530
6531 @Test
6532 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
6533 mService.setPreferencesHelper(mPreferencesHelper);
6534 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6535 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6536 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6537 channel1.setConversationId("parent1", "convo 1");
6538 convo1.setNotificationChannel(channel1);
6539 convos.add(convo1);
6540
6541 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6542 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6543 channel2.setConversationId("parent1", "convo 2");
6544 convo2.setNotificationChannel(channel2);
6545 convos.add(convo2);
6546 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6547
6548 List<ConversationChannelWrapper> conversations =
6549 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6550 assertNull(conversations.get(0).getShortcutInfo());
6551 assertNull(conversations.get(1).getShortcutInfo());
6552 }
Mady Mellor57b34162020-04-01 08:44:00 -07006553
6554 @Test
6555 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
6556 mService.setShortcutHelper(null);
6557 NotificationRecord nr =
6558 generateMessageBubbleNotifRecord(mTestNotificationChannel,
6559 "testShortcutHelperNull_doesntCrashEnqueue");
6560 try {
6561 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6562 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6563 waitForIdle();
6564 } catch (Exception e) {
6565 fail(e.getMessage());
6566 }
6567 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05006568}