blob: cd40dc9b288320e1ed3b7847f014fc1b29c0a2f5 [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 Reynoldsfa273072020-04-14 15:31:21 -0400116import android.content.pm.ShortcutServiceInternal;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400117import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200118import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400119import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700120import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400121import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400122import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500123import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400124import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400125import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400126import android.os.IBinder;
Julia Reynolds0f767342019-12-18 09:11:55 -0500127import android.os.Parcel;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400128import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400129import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700130import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500131import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400132import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000133import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600134import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000135import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400136import android.service.notification.Adjustment;
Julia Reynolds882f2062020-02-05 12:11:38 -0500137import android.service.notification.ConversationChannelWrapper;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400138import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400139import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500140import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400141import android.service.notification.ZenPolicy;
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400142import android.telephony.TelephonyManager;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400143import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400144import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400145import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400146import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400147import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400148import android.testing.TestablePermissions;
Julia Reynolds57a974b2019-10-07 11:51:47 -0400149import android.testing.TestableResources;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400150import android.text.Html;
Julia Reynolds0f767342019-12-18 09:11:55 -0500151import android.text.TextUtils;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400152import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000153import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400154import android.util.AtomicFile;
Julia Reynolds469144c2019-06-21 14:30:28 -0400155import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400156import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400157
Mady Mellor49b1bf12019-03-29 12:00:02 -0700158import androidx.annotation.Nullable;
159import androidx.test.InstrumentationRegistry;
160
Tony Mak9a3c1f12019-03-04 16:04:42 +0000161import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Will Brockmancfd98302020-01-29 15:57:30 -0500162import com.android.internal.logging.InstanceIdSequence;
163import com.android.internal.logging.InstanceIdSequenceFake;
Julia Reynolds503ed942017-10-04 16:04:56 -0400164import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400165import com.android.internal.util.FastXmlSerializer;
Mady Mellor13f9bc82020-03-24 19:09:28 -0700166import com.android.server.DeviceIdleInternal;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700167import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400168import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500169import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400170import com.android.server.lights.LightsManager;
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100171import com.android.server.lights.LogicalLight;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400172import com.android.server.notification.NotificationManagerService.NotificationAssistants;
173import com.android.server.notification.NotificationManagerService.NotificationListeners;
Bernardo Rufino18725b62020-01-21 14:12:43 +0000174import com.android.server.statusbar.StatusBarManagerInternal;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700175import com.android.server.uri.UriGrantsManagerInternal;
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000176import com.android.server.wm.ActivityTaskManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400177import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400178
179import org.junit.After;
180import org.junit.Before;
181import org.junit.Test;
182import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500183import org.mockito.ArgumentCaptor;
184import org.mockito.Mock;
185import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400186import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400187import org.xmlpull.v1.XmlPullParser;
188import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500189
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400190import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400191import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400192import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400193import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400194import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400195import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400196import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500197import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000198import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400199import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400200import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200201import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500202
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400203
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400204@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400205@RunWith(AndroidTestingRunner.class)
206@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500207public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500208 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000209
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400210 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500211 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500212 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400213 private NotificationManagerInternal mInternalService;
Mady Mellor56515c42020-02-18 17:58:36 -0800214 private ShortcutHelper mShortcutHelper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400215 @Mock
216 private IPackageManager mPackageManager;
217 @Mock
218 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400219 @Mock
220 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400221 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500222 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400223 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400224 @Mock
225 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400226 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400227 AtomicFile mPolicyFile;
228 File mFile;
229 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400230 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400231 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400232 private UsageStatsManagerInternal mAppUsageStats;
233 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400234 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400235 @Mock
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800236 private LauncherApps mLauncherApps;
237 @Mock
Julia Reynoldsfa273072020-04-14 15:31:21 -0400238 private ShortcutServiceInternal mShortcutServiceInternal;
239 @Mock
Julia Reynolds68263d12017-06-21 14:21:19 -0400240 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200241 @Mock
242 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400243 @Mock
244 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400245
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500246 private static final int MAX_POST_DELAY = 1000;
247
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500248 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500249 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000250
251 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
252
Julia Reynoldsda781472017-04-12 09:41:16 -0400253 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400254 private NotificationListeners mListeners;
255 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400256 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400257 private ManagedServices.ManagedServiceInfo mListener;
258 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400259 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400260 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400261 @Mock
262 IBinder mPermOwner;
263 @Mock
264 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700265 @Mock
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000266 ActivityTaskManagerInternal mAtm;
267 @Mock
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700268 IUriGrantsManager mUgm;
269 @Mock
270 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400271 @Mock
272 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000273 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000274 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
275 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400276 @Mock
277 UserManager mUm;
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500278 @Mock
279 NotificationHistoryManager mHistoryManager;
Yotam Aron74299972020-01-16 16:20:58 +0200280 @Mock
281 StatsManager mStatsManager;
Will Brockman2b6959e2020-01-22 09:59:50 -0500282 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
Will Brockmancfd98302020-01-29 15:57:30 -0500283 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
284 1 << 30);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000285 @Mock
286 StatusBarManagerInternal mStatusBar;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500287
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400288 // Use a Testable subclass so we can simulate calls from the system without failing.
289 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500290 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700291 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000292 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000293 @Nullable
294 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500295
Will Brockmancfd98302020-01-29 15:57:30 -0500296 TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
297 InstanceIdSequence notificationInstanceIdSequence) {
298 super(context, logger, notificationInstanceIdSequence);
Amith Yamasani803eab692017-11-09 17:47:04 -0800299 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400300
Mady Mellor56515c42020-02-18 17:58:36 -0800301 RankingHelper getRankingHelper() {
302 return mRankingHelper;
303 }
304
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400305 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400306 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500307 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700308 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400309 }
310
311 @Override
312 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500313 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700314 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400315 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400316
317 @Override
318 protected ICompanionDeviceManager getCompanionManager() {
319 return null;
320 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800321
322 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800323 protected void reportUserInteraction(NotificationRecord r) {
324 return;
325 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500326
327 @Override
328 protected void handleSavePolicyFile() {
329 return;
330 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000331
332 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000333 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
334 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000335 countLogSmartSuggestionsVisible++;
336 }
337
Annie Meng8b646fd2019-02-01 18:46:42 +0000338 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000339 protected void setNotificationAssistantAccessGrantedForUserInternal(
340 ComponentName assistant, int userId, boolean granted) {
341 if (mNotificationAssistantAccessGrantedCallback != null) {
342 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
343 return;
344 }
345 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
346 }
347
348 private void setNotificationAssistantAccessGrantedCallback(
349 @Nullable NotificationAssistantAccessGrantedCallback callback) {
350 this.mNotificationAssistantAccessGrantedCallback = callback;
351 }
352
353 interface NotificationAssistantAccessGrantedCallback {
354 void onGranted(ComponentName assistant, int userId, boolean granted);
355 }
Mady Mellor56515c42020-02-18 17:58:36 -0800356 }
357
Beverly58b24532018-10-02 09:08:23 -0400358 private class TestableToastCallback extends ITransientNotification.Stub {
359 @Override
360 public void show(IBinder windowToken) {
361 }
362
363 @Override
364 public void hide() {
365 }
366 }
367
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500368 @Before
369 public void setUp() throws Exception {
Beverly24d103b2020-02-18 17:40:57 -0500370 // Shell permisssions will override permissions of our app, so add all necessary permissions
Beverly080782f2020-02-24 16:42:57 -0500371 // for this test here:
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000372 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Beverly24d103b2020-02-18 17:40:57 -0500373 "android.permission.WRITE_DEVICE_CONFIG",
374 "android.permission.READ_DEVICE_CONFIG",
375 "android.permission.READ_CONTACTS");
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000376
Julia Reynoldsda781472017-04-12 09:41:16 -0400377 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400378
Mady Mellor13f9bc82020-03-24 19:09:28 -0700379 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
380 when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
381 ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
382
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700383 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
384 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400385 LocalServices.removeServiceForTest(WindowManagerInternal.class);
386 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000387 LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
388 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
Mady Mellor13f9bc82020-03-24 19:09:28 -0700389 LocalServices.removeServiceForTest(DeviceIdleInternal.class);
390 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
391 LocalServices.removeServiceForTest(ActivityManagerInternal.class);
392 LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700393
Julia Reynolds4afe2642019-05-01 08:42:24 -0400394 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
395
Will Brockmancfd98302020-01-29 15:57:30 -0500396 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
397 mNotificationInstanceIdSequence);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500398
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400399 // Use this testable looper.
400 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500401 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400402 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400403
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400404 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400405 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
406 Object[] args = invocation.getArguments();
407 return getApplicationInfo((String) args[0], mUid);
408 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500409 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400410 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
411 Object[] args = invocation.getArguments();
412 return getApplicationInfo((String) args[0], mUid);
413 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400414 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500415 final LightsManager mockLightsManager = mock(LightsManager.class);
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100416 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400417 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400418 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700419 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400420 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400421 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400422 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500423
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400424 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400425 mFile = new File(mContext.getCacheDir(), "test.xml");
426 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400427 final String preupgradeXml = "<notification-policy></notification-policy>";
428 mPolicyFile = new AtomicFile(mFile);
429 FileOutputStream fos = mPolicyFile.startWrite();
430 fos.write(preupgradeXml.getBytes());
431 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400432
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400433 // Setup managed services
434 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400435 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400436 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
437 ArraySet<ComponentName> components = new ArraySet<>();
438 components.add(defaultComponent);
439 when(mListeners.getDefaultComponents()).thenReturn(components);
440 when(mConditionProviders.getDefaultPackages())
441 .thenReturn(new ArraySet<>(Arrays.asList("config")));
442 when(mAssistants.getDefaultComponents()).thenReturn(components);
443 when(mAssistants.queryPackageForServices(
444 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400445 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
446 ManagedServices.Config listenerConfig = new ManagedServices.Config();
447 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
448 when(mListeners.getConfig()).thenReturn(listenerConfig);
449 ManagedServices.Config assistantConfig = new ManagedServices.Config();
450 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
451 when(mAssistants.getConfig()).thenReturn(assistantConfig);
452 ManagedServices.Config dndConfig = new ManagedServices.Config();
453 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
454 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
455
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400456 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
457
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500458 mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
459 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400460 mListeners, mAssistants, mConditionProviders,
461 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000462 mGroupHelper, mAm, mAtm, mAppUsageStats,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400463 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400464 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
465 mock(TelephonyManager.class));
Julia Reynolds4afe2642019-05-01 08:42:24 -0400466 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
467
Julia Reynolds503ed942017-10-04 16:04:56 -0400468 mService.setAudioManager(mAudioManager);
Mady Mellor56515c42020-02-18 17:58:36 -0800469
470 mShortcutHelper = mService.getShortcutHelper();
471 mShortcutHelper.setLauncherApps(mLauncherApps);
Julia Reynoldsfa273072020-04-14 15:31:21 -0400472 mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
Mady Mellor56515c42020-02-18 17:58:36 -0800473
474 // Set the testable bubble extractor
475 RankingHelper rankingHelper = mService.getRankingHelper();
476 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
Mady Mellora92268c2020-03-09 17:25:08 -0700477 extractor.setActivityManager(mActivityManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500478
479 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400480 mBinderService = mService.getBinderService();
481 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500482
483 mBinderService.createNotificationChannels(
484 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400485 assertNotNull(mBinderService.getNotificationChannel(
486 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400487 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500488 }
489
Julia Reynoldsb852e562017-06-06 16:14:18 -0400490 @After
Will Brockman9918db92020-03-06 16:48:39 -0500491 public void assertNotificationRecordLoggerCallsValid() {
492 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
493 if (call.wasLogged) {
494 assertNotNull(call.event);
495 }
496 }
497 }
498
499 @After
Julia Reynoldsb852e562017-06-06 16:14:18 -0400500 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400501 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000502 clearDeviceConfig();
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500503 mService.unregisterDeviceConfigChange();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000504 InstrumentationRegistry.getInstrumentation()
505 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400506 }
507
Jay Aliomer4204f252019-08-26 11:36:53 -0400508 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
509 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
510 changed.put(true, new ArrayList<>());
511 changed.put(false, new ArrayList<>());
512 return changed;
513 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400514 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
515 final ApplicationInfo applicationInfo = new ApplicationInfo();
516 applicationInfo.uid = uid;
517 switch (pkg) {
518 case PKG_N_MR1:
519 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
520 break;
521 case PKG_O:
522 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
523 break;
524 case PKG_P:
525 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
526 break;
527 default:
528 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
529 break;
530 }
531 return applicationInfo;
532 }
533
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500534 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400535 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500536 }
537
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500538 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
Mady Mellora92268c2020-03-09 17:25:08 -0700539 int pkgPref, boolean channelEnabled) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500540 Settings.Global.putInt(mContext.getContentResolver(),
541 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
542 mService.mPreferencesHelper.updateBubblesEnabled();
543 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled());
544 try {
Mady Mellora92268c2020-03-09 17:25:08 -0700545 mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500546 } catch (RemoteException e) {
547 e.printStackTrace();
548 }
Mady Mellorc6820342019-05-20 12:04:36 -0700549 mTestNotificationChannel.setAllowBubbles(channelEnabled);
550 }
551
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500552 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
553 Notification.Builder nb = new Notification.Builder(mContext, "a")
554 .setContentTitle("foo")
555 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400556 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
557 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500558 nb.build(), new UserHandle(userId), null, postTime);
559 return sbn;
560 }
561
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400562 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
563 String groupKey, boolean isSummary) {
564 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
565 .setContentTitle("foo")
566 .setSmallIcon(android.R.drawable.sym_def_app_icon)
567 .setGroup(groupKey)
568 .setGroupSummary(isSummary);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400569 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
570 "tag" + System.currentTimeMillis(), mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400571 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000572 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400573 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400574
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500575 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500576 return generateNotificationRecord(channel, null);
577 }
578
579 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
580 Notification.TvExtender extender) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500581 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500582 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500583 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500584 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500585 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500586 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500587 if (extender != null) {
588 nb.extend(extender);
589 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400590 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400591 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000592 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500593 }
594
Aran Inkfd2bfd32019-10-04 16:30:01 -0400595 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
596 if (channel == null) {
597 channel = mTestNotificationChannel;
598 }
599 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
600 .setContentTitle("foo")
601 .setSmallIcon(android.R.drawable.sym_def_app_icon);
602 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
603 nb.build(), new UserHandle(userId), null, 0);
604 return new NotificationRecord(mContext, sbn, channel);
605 }
606
Mady Mellor9e923e12019-12-17 16:08:46 -0800607 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
608 String tag) {
609 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
610 }
611
612 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
613 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
614 if (channel == null) {
615 channel = mTestNotificationChannel;
616 }
617 if (tag == null) {
618 tag = "tag";
619 }
620 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
621 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
622 tag, mUid, 0,
623 nb.build(), new UserHandle(mUid), null, 0);
624 return new NotificationRecord(mContext, sbn, channel);
625 }
626
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400627 private Map<String, Answer> getSignalExtractorSideEffects() {
628 Map<String, Answer> answers = new ArrayMap<>();
629
630 answers.put("override group key", invocationOnMock -> {
631 ((NotificationRecord) invocationOnMock.getArguments()[0])
632 .setOverrideGroupKey("bananas");
633 return null;
634 });
635 answers.put("override people", invocationOnMock -> {
636 ((NotificationRecord) invocationOnMock.getArguments()[0])
637 .setPeopleOverride(new ArrayList<>());
638 return null;
639 });
640 answers.put("snooze criteria", invocationOnMock -> {
641 ((NotificationRecord) invocationOnMock.getArguments()[0])
642 .setSnoozeCriteria(new ArrayList<>());
643 return null;
644 });
645 answers.put("notification channel", invocationOnMock -> {
646 ((NotificationRecord) invocationOnMock.getArguments()[0])
647 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
648 return null;
649 });
650 answers.put("badging", invocationOnMock -> {
651 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
652 r.setShowBadge(!r.canShowBadge());
653 return null;
654 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500655 answers.put("bubbles", invocationOnMock -> {
656 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
657 r.setAllowBubble(!r.canBubble());
658 return null;
659 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400660 answers.put("package visibility", invocationOnMock -> {
661 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
662 Notification.VISIBILITY_SECRET);
663 return null;
664 });
665
666 return answers;
667 }
668
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400669 private void clearDeviceConfig() {
670 DeviceConfig.resetToDefaults(
671 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
672 }
673
674 private void setDefaultAssistantInDeviceConfig(String componentName) {
675 DeviceConfig.setProperty(
676 DeviceConfig.NAMESPACE_SYSTEMUI,
677 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
678 componentName,
679 false);
680 }
681
Mady Mellor9e923e12019-12-17 16:08:46 -0800682 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
683 String groupKey, boolean isSummary) {
684 // Give it a person
685 Person person = new Person.Builder()
686 .setName("bubblebot")
687 .build();
Mady Mellor9e923e12019-12-17 16:08:46 -0800688 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
689 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
690 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
691 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
692 inputIntent).addRemoteInput(remoteInput)
693 .build();
694 // Make it messaging style
695 Notification.Builder nb = new Notification.Builder(mContext,
696 mTestNotificationChannel.getId())
697 .setContentTitle("foo")
698 .setStyle(new Notification.MessagingStyle(person)
699 .setConversationTitle("Bubble Chat")
700 .addMessage("Hello?",
701 SystemClock.currentThreadTimeMillis() - 300000, person)
702 .addMessage("Is it me you're looking for?",
703 SystemClock.currentThreadTimeMillis(), person)
704 )
705 .setActions(replyAction)
706 .setSmallIcon(android.R.drawable.sym_def_app_icon)
707 .setGroupSummary(isSummary);
708 if (groupKey != null) {
709 nb.setGroup(groupKey);
710 }
711 if (addBubbleMetadata) {
Mady Mellora92268c2020-03-09 17:25:08 -0700712 nb.setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -0800713 }
714 return nb;
715 }
716
Mady Mellora92268c2020-03-09 17:25:08 -0700717 private Notification.BubbleMetadata getBubbleMetadata() {
718 PendingIntent pendingIntent = mock(PendingIntent.class);
719 Intent intent = mock(Intent.class);
720 when(pendingIntent.getIntent()).thenReturn(intent);
721
722 ActivityInfo info = new ActivityInfo();
723 info.resizeMode = RESIZE_MODE_RESIZEABLE;
724 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
725
726 return new Notification.BubbleMetadata.Builder(
727 pendingIntent,
728 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
729 .build();
730 }
731
Mady Mellor22f2f072019-04-18 13:26:18 -0700732 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
733 throws RemoteException {
734
Mady Mellor9e923e12019-12-17 16:08:46 -0800735 String groupKey = "BUBBLE_GROUP";
Mady Mellor22f2f072019-04-18 13:26:18 -0700736
Mady Mellor9e923e12019-12-17 16:08:46 -0800737 // Notification that has bubble metadata
738 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
739 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
Mady Mellor22f2f072019-04-18 13:26:18 -0700740
Julia Reynolds24edc002020-01-29 16:35:32 -0500741 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
742 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
743 nrBubble.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700744 waitForIdle();
745
746 // Make sure we are a bubble
747 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
748 assertEquals(1, notifsAfter.length);
749 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
750
Mady Mellor9e923e12019-12-17 16:08:46 -0800751 // Notification without bubble metadata
752 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
753 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
754
Julia Reynolds24edc002020-01-29 16:35:32 -0500755 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
756 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
757 nrPlain.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700758 waitForIdle();
759
760 notifsAfter = mBinderService.getActiveNotifications(PKG);
761 assertEquals(2, notifsAfter.length);
762
763 // Summary notification for both of those
Mady Mellor9e923e12019-12-17 16:08:46 -0800764 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
765 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
766
Mady Mellor22f2f072019-04-18 13:26:18 -0700767 if (summaryAutoCancel) {
768 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
769 }
Julia Reynolds24edc002020-01-29 16:35:32 -0500770 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
771 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
772 nrSummary.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700773 waitForIdle();
774
775 notifsAfter = mBinderService.getActiveNotifications(PKG);
776 assertEquals(3, notifsAfter.length);
777
778 return nrSummary;
779 }
780
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500781 @Test
Jay Aliomerfea80252019-11-20 18:14:24 -0500782 public void testDefaultAssistant_overrideDefault() {
783 final int userId = 0;
784 final String testComponent = "package/class";
785 final List<UserInfo> userInfos = new ArrayList<>();
786 userInfos.add(new UserInfo(0, "", 0));
787 final ArraySet<ComponentName> validAssistants = new ArraySet<>();
788 validAssistants.add(ComponentName.unflattenFromString(testComponent));
Jay Aliomerfea80252019-11-20 18:14:24 -0500789 when(mActivityManager.isLowRamDevice()).thenReturn(false);
790 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
791 .thenReturn(validAssistants);
Jay Aliomer76e1f2722020-03-05 12:36:38 -0500792 when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
Jay Aliomerfea80252019-11-20 18:14:24 -0500793 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
794
795 mService.setDefaultAssistantForUser(userId);
796
797 verify(mAssistants).setPackageOrComponentEnabled(
798 eq(testComponent), eq(userId), eq(true), eq(true));
Jay Aliomerfea80252019-11-20 18:14:24 -0500799 }
800
801 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500802 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500803 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500804 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400805 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500806 new ParceledListSlice(Arrays.asList(channel)));
807 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400808 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500809 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500810 }
811
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500812 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500813 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500814 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400815 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200816 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500817 fail("Exception should be thrown immediately.");
818 } catch (NullPointerException e) {
819 // pass
820 }
821 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500822
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500823 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500824 public void testCreateNotificationChannels_TwoChannels() throws Exception {
825 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500826 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500827 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500828 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400829 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500830 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400831 assertTrue(mBinderService.getNotificationChannel(
832 PKG, mContext.getUserId(), PKG, "id1") != null);
833 assertTrue(mBinderService.getNotificationChannel(
834 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500835 }
836
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500837 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400838 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
839 throws Exception {
840 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500841 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400842 mBinderService.createNotificationChannels(PKG,
843 new ParceledListSlice(Arrays.asList(channel)));
844
845 // Recreating the channel doesn't throw, but ignores importance.
846 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400847 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400848 mBinderService.createNotificationChannels(PKG,
849 new ParceledListSlice(Arrays.asList(dupeChannel)));
850 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400851 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500852 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400853 }
854
855 @Test
856 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
857 throws Exception {
858 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500859 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400860 mBinderService.createNotificationChannels(PKG,
861 new ParceledListSlice(Arrays.asList(channel)));
862
863 // Recreating with a lower importance is allowed to modify the channel.
864 final NotificationChannel dupeChannel =
865 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
866 mBinderService.createNotificationChannels(PKG,
867 new ParceledListSlice(Arrays.asList(dupeChannel)));
868 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400869 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400870 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
871 }
872
873 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400874 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
875 throws Exception {
876 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500877 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400878 mBinderService.createNotificationChannels(PKG,
879 new ParceledListSlice(Arrays.asList(channel)));
880
881 // The user modifies importance directly, can no longer be changed by the app.
882 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400883 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400884 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
885
886 // Recreating with a lower importance leaves channel unchanged.
887 final NotificationChannel dupeChannel =
888 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
889 mBinderService.createNotificationChannels(PKG,
890 new ParceledListSlice(Arrays.asList(dupeChannel)));
891 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400892 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400893 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400894 }
895
896 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500897 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
898 throws Exception {
899 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500900 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500901 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400902 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400903 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500904 new ParceledListSlice(Arrays.asList(channel1, channel2)));
905 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400906 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500907 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500908 }
909
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500910 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500911 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500912 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
913
914 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400915 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500916 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400917
918 // isBlocked is only used for user blocking, not app suspension
919 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500920 }
921
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500922 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500923 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500924 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
925
926 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400927 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500928 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400929 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400930 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400931
932 mBinderService.createNotificationChannels(
933 PKG, new ParceledListSlice(Arrays.asList(channel)));
Julia Reynolds24edc002020-01-29 16:35:32 -0500934 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400935 mBinderService.enqueueNotificationWithTag(PKG, PKG,
936 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400937 sbn.getId(), sbn.getNotification(), sbn.getUserId());
938 waitForIdle();
939 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
940 }
941
942 @Test
943 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
944 throws Exception {
945 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
946
947 NotificationChannel channel = new NotificationChannel("blocked", "name",
948 NotificationManager.IMPORTANCE_NONE);
949 mBinderService.createNotificationChannels(
950 PKG, new ParceledListSlice(Arrays.asList(channel)));
951
Julia Reynolds24edc002020-01-29 16:35:32 -0500952 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -0400953 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400954 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400955 sbn.getId(), sbn.getNotification(), sbn.getUserId());
956 waitForIdle();
957 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
958 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400959 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400960 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
961 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400962 }
963
964 @Test
965 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
966 throws Exception {
967 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
968
969 NotificationChannel channel =
970 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
971 mBinderService.createNotificationChannels(
972 PKG, new ParceledListSlice(Arrays.asList(channel)));
973
974 NotificationChannel update =
975 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
976 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
977 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400978 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
979 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400980
Julia Reynolds24edc002020-01-29 16:35:32 -0500981 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -0400982 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400983 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400984 sbn.getId(), sbn.getNotification(), sbn.getUserId());
985 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700986 // The first time a foreground service notification is shown, we allow the channel
987 // to be updated to allow it to be seen.
988 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
989 assertEquals(IMPORTANCE_LOW,
990 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400991 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
992 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400993 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700994 waitForIdle();
995
996 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
997 update.setFgServiceShown(true);
998 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
999 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001000 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1001 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001002
Julia Reynolds24edc002020-01-29 16:35:32 -05001003 sbn = generateNotificationRecord(channel).getSbn();
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001004 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001005 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1006 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001007 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1008 waitForIdle();
1009 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001010 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001011 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001012 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1013 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001014 }
1015
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001016 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -04001017 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1018 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001019 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001020 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1021 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -04001022
1023 NotificationChannel channel = new NotificationChannel("id", "name",
1024 NotificationManager.IMPORTANCE_HIGH);
1025 channel.setGroup("something");
1026 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -04001027 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -04001028 verify(mUsageStats, times(1)).registerBlocked(eq(r));
1029 }
1030
1031 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -04001032 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001033 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1034
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001035 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -04001036
Julia Reynolds24edc002020-01-29 16:35:32 -05001037 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001038 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1039 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -04001040 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1041 waitForIdle();
1042 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001043 }
1044
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001045 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001046 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1047 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1048
1049 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1050
Julia Reynolds24edc002020-01-29 16:35:32 -05001051 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001052 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001053 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1054 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001055 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1056 waitForIdle();
1057 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001058 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001059 }
1060
Brad Stenning8c991ea2018-07-31 13:33:01 -07001061 /**
1062 * Confirm the system user on automotive devices can use car categories
1063 */
1064 @Test
1065 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
1066 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1067 .thenReturn(true);
1068 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1069 Notification.CATEGORY_CAR_WARNING,
1070 Notification.CATEGORY_CAR_INFORMATION);
1071 int id = 0;
1072 for (String category: categories) {
1073 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001074 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001075 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001076 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1077 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001078 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1079 }
1080 waitForIdle();
1081 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1082 }
1083
1084
1085 /**
1086 * Confirm restricted notification categories only apply to automotive.
1087 */
1088 @Test
1089 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1090 mService.isSystemUid = false;
1091 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1092 .thenReturn(false);
1093 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1094 Notification.CATEGORY_CAR_WARNING,
1095 Notification.CATEGORY_CAR_INFORMATION);
1096 int id = 0;
1097 for (String category: categories) {
1098 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001099 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001100 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001101 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1102 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001103 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1104 }
1105 waitForIdle();
1106 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1107 }
1108
1109 /**
1110 * Confirm if a non-system user tries to use the car categories on a automotive device that
1111 * they will get a security exception
1112 */
1113 @Test
1114 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1115 mService.isSystemUid = false;
1116 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1117 .thenReturn(true);
1118 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1119 Notification.CATEGORY_CAR_WARNING,
1120 Notification.CATEGORY_CAR_INFORMATION);
1121 for (String category: categories) {
Julia Reynolds24edc002020-01-29 16:35:32 -05001122 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001123 sbn.getNotification().category = category;
1124 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001125 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1126 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001127 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1128 fail("Calls from non system apps should not allow use of restricted categories");
1129 } catch (SecurityException e) {
1130 // pass
1131 }
1132 }
1133 waitForIdle();
1134 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1135 }
1136
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001137 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001138 public void testBlockedNotifications_blockedByAssistant() throws Exception {
1139 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001140 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001141
1142 NotificationChannel channel = new NotificationChannel("id", "name",
1143 NotificationManager.IMPORTANCE_HIGH);
1144 NotificationRecord r = generateNotificationRecord(channel);
1145 mService.addEnqueuedNotification(r);
1146
Julia Reynolds27c0a962018-12-10 12:37:28 -05001147 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001148 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001149 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05001150 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05001151 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001152
1153 NotificationManagerService.PostNotificationRunnable runnable =
1154 mService.new PostNotificationRunnable(r.getKey());
1155 runnable.run();
1156 waitForIdle();
1157
1158 verify(mUsageStats, never()).registerPostedByApp(any());
1159 }
1160
1161 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001162 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001163 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1164 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001165 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001166 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001167 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001168 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001169 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001170 }
1171
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001172 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001173 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
Will Brockman2b6959e2020-01-22 09:59:50 -05001174 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1175 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1176 generateNotificationRecord(null).getNotification(), 0);
1177 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001178 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001179
Will Brockman2b6959e2020-01-22 09:59:50 -05001180 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
Will Brockman9918db92020-03-06 16:48:39 -05001181 assertTrue(call.wasLogged);
Will Brockman75c60572020-01-31 10:30:27 -05001182 assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1183 call.event);
Will Brockman2b6959e2020-01-22 09:59:50 -05001184 assertNotNull(call.r);
1185 assertNull(call.old);
1186 assertEquals(0, call.position);
1187 assertEquals(0, call.buzzBeepBlink);
Julia Reynolds24edc002020-01-29 16:35:32 -05001188 assertEquals(PKG, call.r.getSbn().getPackageName());
1189 assertEquals(0, call.r.getSbn().getId());
1190 assertEquals(tag, call.r.getSbn().getTag());
Will Brockman4f0f9d22020-02-23 21:18:11 -05001191 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order
Will Brockman2b6959e2020-01-22 09:59:50 -05001192 }
1193
1194 @Test
1195 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1196 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1197 Notification original = new Notification.Builder(mContext,
1198 mTestNotificationChannel.getId())
1199 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1200 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1201 Notification update = new Notification.Builder(mContext,
1202 mTestNotificationChannel.getId())
1203 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1204 .setCategory(Notification.CATEGORY_ALARM).build();
1205 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1206 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001207 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001208
Will Brockman9918db92020-03-06 16:48:39 -05001209 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001210 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001211 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001212 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001213 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001214
Will Brockman9918db92020-03-06 16:48:39 -05001215 assertTrue(mNotificationRecordLogger.get(1).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001216 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001217 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED,
Will Brockman9918db92020-03-06 16:48:39 -05001218 mNotificationRecordLogger.event(1));
Will Brockmancfd98302020-01-29 15:57:30 -05001219 // Instance ID doesn't change on update of an active notification
Will Brockman4f0f9d22020-02-23 21:18:11 -05001220 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman2b6959e2020-01-22 09:59:50 -05001221 }
1222
1223 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001224 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1225 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
Will Brockman2b6959e2020-01-22 09:59:50 -05001226 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1227 generateNotificationRecord(null).getNotification(), 0);
1228 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1229 generateNotificationRecord(null).getNotification(), 0);
1230 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001231 assertEquals(2, mNotificationRecordLogger.numCalls());
1232 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockmand3d49332020-02-10 19:43:03 -05001233 assertEquals(
1234 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001235 mNotificationRecordLogger.event(0));
1236 assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1237 assertNull(mNotificationRecordLogger.event(1));
Will Brockmand3d49332020-02-10 19:43:03 -05001238 }
1239
1240 @Test
1241 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1242 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1243 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1244 generateNotificationRecord(null).getNotification(),
1245 0);
1246 final Notification notif = generateNotificationRecord(null).getNotification();
1247 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1248 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1249 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001250 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001251 assertEquals(
1252 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001253 mNotificationRecordLogger.event(0));
1254 assertNull(mNotificationRecordLogger.event(1));
Will Brockman2b6959e2020-01-22 09:59:50 -05001255 }
1256
1257 @Test
Will Brockmancfd98302020-01-29 15:57:30 -05001258 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1259 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1260 Notification notification = new Notification.Builder(mContext,
1261 mTestNotificationChannel.getId())
1262 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1263 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1264 waitForIdle();
1265 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1266 waitForIdle();
1267 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1268 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001269 assertEquals(3, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001270
Will Brockmancfd98302020-01-29 15:57:30 -05001271 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001272 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001273 mNotificationRecordLogger.event(0));
1274 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman4f0f9d22020-02-23 21:18:11 -05001275 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001276
Will Brockmancfd98302020-01-29 15:57:30 -05001277 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001278 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
Will Brockman9918db92020-03-06 16:48:39 -05001279 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001280 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001281
1282 assertEquals(
1283 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001284 mNotificationRecordLogger.event(2));
1285 assertTrue(mNotificationRecordLogger.get(2).wasLogged);
Will Brockmancfd98302020-01-29 15:57:30 -05001286 // New instance ID because notification was canceled before re-post
Will Brockman4f0f9d22020-02-23 21:18:11 -05001287 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001288 }
1289
1290 @Test
1291 public void testCancelNonexistentNotification() throws Exception {
1292 mBinderService.cancelNotificationWithTag(PKG, PKG,
1293 "testCancelNonexistentNotification", 0, 0);
1294 waitForIdle();
1295 // The notification record logger doesn't even get called when a nonexistent notification
1296 // is cancelled, because that happens very frequently and is not interesting.
Will Brockman9918db92020-03-06 16:48:39 -05001297 assertEquals(0, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001298 }
1299
1300 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001301 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001302 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1303 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001304 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001305 mBinderService.cancelNotificationWithTag(PKG, PKG,
1306 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001307 waitForIdle();
1308 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001309 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001310 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001311 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001312 }
1313
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001314 @Test
Evan Lairdd04af512020-01-09 11:18:09 -05001315 public void testPostCancelPostNotifiesListeners() throws Exception {
1316 // WHEN a notification is posted
1317 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1318 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1319 sbn.getNotification(), sbn.getUserId());
1320 // THEN it is canceled
1321 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1322 // THEN it is posted again (before the cancel has a chance to finish)
1323 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1324 sbn.getNotification(), sbn.getUserId());
1325 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
1326 waitForIdle();
1327
1328 // The final enqueue made it to the listener instead of being canceled
1329 StatusBarNotification[] notifs =
1330 mBinderService.getActiveNotifications(PKG);
1331 assertEquals(1, notifs.length);
1332 assertEquals(1, mService.getNotificationRecordCount());
1333 }
1334
1335 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001336 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001337 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1338 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001339 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001340 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001341 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1342 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001343 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001344 mBinderService.cancelNotificationWithTag(PKG, PKG,
1345 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001346 waitForIdle();
1347 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001348 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001349 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001350 assertEquals(0, mService.getNotificationRecordCount());
1351 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1352 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1353 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001354 }
1355
1356 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001357 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001358 NotificationRecord r = generateNotificationRecord(null);
Julia Reynolds24edc002020-01-29 16:35:32 -05001359 final StatusBarNotification sbn = r.getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001360 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1361 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001362 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001363 mBinderService.cancelNotificationsFromListener(null, null);
1364 waitForIdle();
1365 StatusBarNotification[] notifs =
1366 mBinderService.getActiveNotifications(sbn.getPackageName());
1367 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001368 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001369 }
1370
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001371 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001372 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001373 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001374 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1375 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001376 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001377 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001378 waitForIdle();
1379 StatusBarNotification[] notifs =
1380 mBinderService.getActiveNotifications(sbn.getPackageName());
1381 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001382 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001383 }
1384
1385 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001386 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1387 throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001388 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001389 sbn.getNotification().flags =
1390 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1391 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1392 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1393 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1394 waitForIdle();
1395 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1396 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1397 }
1398
1399 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001400 public void testUserInitiatedClearAll_noLeak() throws Exception {
1401 final NotificationRecord n = generateNotificationRecord(
1402 mTestNotificationChannel, 1, "group", true);
1403
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001404 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1405 "testUserInitiatedClearAll_noLeak",
Julia Reynolds24edc002020-01-29 16:35:32 -05001406 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001407 waitForIdle();
1408
Julia Reynolds503ed942017-10-04 16:04:56 -04001409 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001410 n.getUserId());
1411 waitForIdle();
1412 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001413 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
Julia Reynolds080361e2017-07-13 11:23:12 -04001414 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001415 assertEquals(0, mService.getNotificationRecordCount());
1416 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1417 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1418 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001419 }
1420
1421 @Test
1422 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1423 final NotificationRecord parent = generateNotificationRecord(
1424 mTestNotificationChannel, 1, "group1", true);
1425 final NotificationRecord child = generateNotificationRecord(
1426 mTestNotificationChannel, 2, "group1", false);
1427
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001428 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1429 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001430 parent.getSbn().getId(), parent.getSbn().getNotification(),
1431 parent.getSbn().getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001432 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1433 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001434 child.getSbn().getId(), child.getSbn().getNotification(),
1435 child.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001436 waitForIdle();
1437
Julia Reynolds24edc002020-01-29 16:35:32 -05001438 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001439 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001440 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001441 }
1442
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001443 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001444 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001445 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds0839c022017-06-15 15:24:01 -04001446 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001447 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1448 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001449 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1450 }
1451 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1452 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001453
Julia Reynolds503ed942017-10-04 16:04:56 -04001454 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001455 }
1456
1457 @Test
1458 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1459 final NotificationRecord parent = generateNotificationRecord(
1460 mTestNotificationChannel, 1, "group1", true);
1461 final NotificationRecord parentAsChild = generateNotificationRecord(
1462 mTestNotificationChannel, 1, "group1", false);
1463 final NotificationRecord child = generateNotificationRecord(
1464 mTestNotificationChannel, 2, "group1", false);
1465
1466 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001467 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1468 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001469 parent.getSbn().getId(), parent.getSbn().getNotification(),
1470 parent.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001471 waitForIdle();
1472
1473 // enqueue the child several times
1474 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001475 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1476 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001477 child.getSbn().getId(), child.getSbn().getNotification(),
1478 child.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001479 }
1480 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001481 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1482 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001483 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
1484 parentAsChild.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001485 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001486
Julia Reynolds503ed942017-10-04 16:04:56 -04001487 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001488 }
1489
1490 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001491 public void testAutobundledSummary_notificationAdded() {
1492 NotificationRecord summary =
1493 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1494 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1495 mService.addNotification(summary);
1496 mService.mSummaryByGroupKey.put("pkg", summary);
1497 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1498 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001499 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001500
Julia Reynolds24edc002020-01-29 16:35:32 -05001501 assertTrue(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001502 }
1503
1504 @Test
1505 public void testAutobundledSummary_notificationRemoved() {
1506 NotificationRecord summary =
1507 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1508 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1509 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1510 mService.addNotification(summary);
1511 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1512 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1513 mService.mSummaryByGroupKey.put("pkg", summary);
1514
Mady Mellor6d775f82019-11-12 16:12:19 -08001515 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001516
Julia Reynolds24edc002020-01-29 16:35:32 -05001517 assertFalse(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001518 }
1519
1520 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001521 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001522 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001523 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001524 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1525 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001526 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001527 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001528 waitForIdle();
1529 StatusBarNotification[] notifs =
1530 mBinderService.getActiveNotifications(sbn.getPackageName());
1531 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001532 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001533 }
1534
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001535 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001536 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001537 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001538 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001539 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1540 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001541 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001542 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1543 waitForIdle();
1544 StatusBarNotification[] notifs =
1545 mBinderService.getActiveNotifications(sbn.getPackageName());
1546 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001547 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001548 }
1549
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001550 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001551 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001552 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001553 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1554 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001555 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001556 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1557 waitForIdle();
1558 StatusBarNotification[] notifs =
1559 mBinderService.getActiveNotifications(sbn.getPackageName());
1560 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001561 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001562 }
1563
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001564 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001565 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001566 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001567 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1568 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001569 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001570 // Null pkg is how we signal a user switch.
1571 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1572 waitForIdle();
1573 StatusBarNotification[] notifs =
1574 mBinderService.getActiveNotifications(sbn.getPackageName());
1575 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001576 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001577 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001578
1579 @Test
Beverly40239d92017-07-07 10:20:41 -04001580 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001581 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Beverly40239d92017-07-07 10:20:41 -04001582 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001583 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1584 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001585 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1586 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1587 waitForIdle();
1588 StatusBarNotification[] notifs =
1589 mBinderService.getActiveNotifications(sbn.getPackageName());
1590 assertEquals(0, notifs.length);
1591 }
1592
1593 @Test
1594 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1595 final NotificationRecord notif = generateNotificationRecord(
1596 mTestNotificationChannel, 1, "group", true);
1597 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001598 mService.addNotification(notif);
1599 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001600 notif.getUserId(), 0, null);
1601 waitForIdle();
1602 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001603 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001604 assertEquals(0, notifs.length);
1605 }
1606
1607 @Test
1608 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1609 final NotificationRecord notif = generateNotificationRecord(
1610 mTestNotificationChannel, 1, "group", true);
1611 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001612 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001613
Julia Reynolds503ed942017-10-04 16:04:56 -04001614 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001615 notif.getUserId());
1616 waitForIdle();
1617 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001618 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001619 assertEquals(1, notifs.length);
1620 }
1621
1622 @Test
1623 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1624 final NotificationRecord parent = generateNotificationRecord(
1625 mTestNotificationChannel, 1, "group", true);
1626 final NotificationRecord child = generateNotificationRecord(
1627 mTestNotificationChannel, 2, "group", false);
1628 final NotificationRecord child2 = generateNotificationRecord(
1629 mTestNotificationChannel, 3, "group", false);
1630 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1631 final NotificationRecord newGroup = generateNotificationRecord(
1632 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001633 mService.addNotification(parent);
1634 mService.addNotification(child);
1635 mService.addNotification(child2);
1636 mService.addNotification(newGroup);
1637 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001638 waitForIdle();
1639 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001640 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001641 assertEquals(1, notifs.length);
1642 }
1643
1644 @Test
1645 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1646 final NotificationRecord parent = generateNotificationRecord(
1647 mTestNotificationChannel, 1, "group", true);
1648 final NotificationRecord child = generateNotificationRecord(
1649 mTestNotificationChannel, 2, "group", false);
1650 final NotificationRecord child2 = generateNotificationRecord(
1651 mTestNotificationChannel, 3, "group", false);
1652 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1653 final NotificationRecord newGroup = generateNotificationRecord(
1654 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001655 mService.addNotification(parent);
1656 mService.addNotification(child);
1657 mService.addNotification(child2);
1658 mService.addNotification(newGroup);
1659 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001660 parent.getUserId());
1661 waitForIdle();
1662 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001663 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001664 assertEquals(1, notifs.length);
1665 }
1666
1667 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001668 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001669 Notification n =
1670 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1671 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1672 .build();
1673 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
1674 n, new UserHandle(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001675 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001676 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001677 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001678 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1679 sbn.getUserId());
1680 waitForIdle();
1681 StatusBarNotification[] notifs =
1682 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001683 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001684 }
1685
1686 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001687 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001688 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001689 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001690 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001691 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001692 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1693 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001694 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001695 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001696 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1697 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001698 waitForIdle();
1699 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001700 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001701 }
1702
1703 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001704 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1705 throws Exception {
1706 final NotificationRecord parent = generateNotificationRecord(
1707 mTestNotificationChannel, 1, "group", true);
1708 final NotificationRecord child = generateNotificationRecord(
1709 mTestNotificationChannel, 2, "group", false);
1710 final NotificationRecord child2 = generateNotificationRecord(
1711 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001712 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001713 final NotificationRecord newGroup = generateNotificationRecord(
1714 mTestNotificationChannel, 4, "group2", false);
1715 mService.addNotification(parent);
1716 mService.addNotification(child);
1717 mService.addNotification(child2);
1718 mService.addNotification(newGroup);
1719 mService.getBinderService().cancelNotificationsFromListener(null, null);
1720 waitForIdle();
1721 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001722 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001723 assertEquals(0, notifs.length);
1724 }
1725
1726 @Test
1727 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1728 throws Exception {
1729 final NotificationRecord parent = generateNotificationRecord(
1730 mTestNotificationChannel, 1, "group", true);
1731 final NotificationRecord child = generateNotificationRecord(
1732 mTestNotificationChannel, 2, "group", false);
1733 final NotificationRecord child2 = generateNotificationRecord(
1734 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001735 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001736 final NotificationRecord newGroup = generateNotificationRecord(
1737 mTestNotificationChannel, 4, "group2", false);
1738 mService.addNotification(parent);
1739 mService.addNotification(child);
1740 mService.addNotification(child2);
1741 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001742 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1743 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001744 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1745 waitForIdle();
1746 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001747 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001748 assertEquals(1, notifs.length);
1749 }
1750
1751 @Test
1752 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1753 final NotificationRecord parent = generateNotificationRecord(
1754 mTestNotificationChannel, 1, "group", true);
1755 final NotificationRecord child = generateNotificationRecord(
1756 mTestNotificationChannel, 2, "group", false);
1757 final NotificationRecord child2 = generateNotificationRecord(
1758 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001759 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001760 final NotificationRecord newGroup = generateNotificationRecord(
1761 mTestNotificationChannel, 4, "group2", false);
1762 mService.addNotification(parent);
1763 mService.addNotification(child);
1764 mService.addNotification(child2);
1765 mService.addNotification(newGroup);
1766 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1767 parent.getUserId());
1768 waitForIdle();
1769 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001770 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001771 assertEquals(0, notifs.length);
1772 }
1773
1774 @Test
Will Brockman8da8c8e2020-04-30 12:46:15 -04001775 public void testGroupInstanceIds() throws Exception {
1776 final NotificationRecord group1 = generateNotificationRecord(
1777 mTestNotificationChannel, 1, "group1", true);
1778 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1779 group1.getSbn().getId(), group1.getSbn().getNotification(),
1780 group1.getSbn().getUserId());
1781 waitForIdle();
1782
1783 // same group, child, should be returned
1784 final NotificationRecord group1Child = generateNotificationRecord(
1785 mTestNotificationChannel, 2, "group1", false);
1786 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1787 group1Child.getSbn().getId(),
1788 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
1789 waitForIdle();
1790
1791 assertEquals(2, mNotificationRecordLogger.numCalls());
1792 assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
1793 mNotificationRecordLogger.get(1).groupInstanceId.getId());
1794 }
1795
1796 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001797 public void testFindGroupNotificationsLocked() throws Exception {
1798 // make sure the same notification can be found in both lists and returned
1799 final NotificationRecord group1 = generateNotificationRecord(
1800 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001801 mService.addEnqueuedNotification(group1);
1802 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001803
1804 // should not be returned
1805 final NotificationRecord group2 = generateNotificationRecord(
1806 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001807 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001808 group2.getSbn().getId(), group2.getSbn().getNotification(),
1809 group2.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001810 waitForIdle();
1811
1812 // should not be returned
1813 final NotificationRecord nonGroup = generateNotificationRecord(
1814 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001815 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001816 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
1817 nonGroup.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001818 waitForIdle();
1819
1820 // same group, child, should be returned
1821 final NotificationRecord group1Child = generateNotificationRecord(
1822 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001823 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001824 group1Child.getSbn().getId(),
1825 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001826 waitForIdle();
1827
1828 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001829 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynolds24edc002020-01-29 16:35:32 -05001830 group1.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001831 assertEquals(3, inGroup1.size());
1832 for (NotificationRecord record : inGroup1) {
1833 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
Julia Reynolds24edc002020-01-29 16:35:32 -05001834 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001835 }
1836 }
1837
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001838 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001839 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1840 final NotificationRecord notif = generateNotificationRecord(
1841 mTestNotificationChannel, 1, "group", true);
1842 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1843 mService.addNotification(notif);
1844 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1845 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1846 waitForIdle();
1847 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001848 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001849 assertEquals(0, notifs.length);
1850 }
1851
1852 @Test
1853 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1854 throws Exception {
1855 final NotificationRecord parent = generateNotificationRecord(
1856 mTestNotificationChannel, 1, "group", true);
1857 final NotificationRecord child = generateNotificationRecord(
1858 mTestNotificationChannel, 2, "group", false);
1859 final NotificationRecord child2 = generateNotificationRecord(
1860 mTestNotificationChannel, 3, "group", false);
1861 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1862 final NotificationRecord newGroup = generateNotificationRecord(
1863 mTestNotificationChannel, 4, "group2", false);
1864 mService.addNotification(parent);
1865 mService.addNotification(child);
1866 mService.addNotification(child2);
1867 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001868 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1869 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001870 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1871 waitForIdle();
1872 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001873 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001874 assertEquals(0, notifs.length);
1875 }
1876
1877 @Test
1878 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001879 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds40f00d72017-12-12 10:47:32 -05001880 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001881 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1882 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001883 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1884 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1885 waitForIdle();
1886 StatusBarNotification[] notifs =
1887 mBinderService.getActiveNotifications(sbn.getPackageName());
1888 assertEquals(0, notifs.length);
1889 }
1890
1891 @Test
1892 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1893 final NotificationRecord notif = generateNotificationRecord(
1894 mTestNotificationChannel, 1, "group", true);
1895 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1896 mService.addNotification(notif);
1897 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1898 notif.getUserId(), 0, null);
1899 waitForIdle();
1900 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001901 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001902 assertEquals(0, notifs.length);
1903 }
1904
1905 @Test
1906 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1907 final NotificationRecord notif = generateNotificationRecord(
1908 mTestNotificationChannel, 1, "group", true);
1909 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1910 mService.addNotification(notif);
1911
1912 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1913 notif.getUserId());
1914 waitForIdle();
1915 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001916 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001917 assertEquals(1, notifs.length);
1918 }
1919
1920 @Test
1921 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1922 final NotificationRecord parent = generateNotificationRecord(
1923 mTestNotificationChannel, 1, "group", true);
1924 final NotificationRecord child = generateNotificationRecord(
1925 mTestNotificationChannel, 2, "group", false);
1926 final NotificationRecord child2 = generateNotificationRecord(
1927 mTestNotificationChannel, 3, "group", false);
1928 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1929 final NotificationRecord newGroup = generateNotificationRecord(
1930 mTestNotificationChannel, 4, "group2", false);
1931 mService.addNotification(parent);
1932 mService.addNotification(child);
1933 mService.addNotification(child2);
1934 mService.addNotification(newGroup);
1935 mService.getBinderService().cancelNotificationsFromListener(null, null);
1936 waitForIdle();
1937 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001938 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001939 assertEquals(1, notifs.length);
1940 }
1941
1942 @Test
1943 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1944 throws Exception {
1945 final NotificationRecord parent = generateNotificationRecord(
1946 mTestNotificationChannel, 1, "group", true);
1947 final NotificationRecord child = generateNotificationRecord(
1948 mTestNotificationChannel, 2, "group", false);
1949 final NotificationRecord child2 = generateNotificationRecord(
1950 mTestNotificationChannel, 3, "group", false);
1951 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1952 final NotificationRecord newGroup = generateNotificationRecord(
1953 mTestNotificationChannel, 4, "group2", false);
1954 mService.addNotification(parent);
1955 mService.addNotification(child);
1956 mService.addNotification(child2);
1957 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001958 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1959 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001960 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1961 waitForIdle();
1962 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001963 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001964 assertEquals(0, notifs.length);
1965 }
1966
1967 @Test
1968 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1969 final NotificationRecord parent = generateNotificationRecord(
1970 mTestNotificationChannel, 1, "group", true);
1971 final NotificationRecord child = generateNotificationRecord(
1972 mTestNotificationChannel, 2, "group", false);
1973 final NotificationRecord child2 = generateNotificationRecord(
1974 mTestNotificationChannel, 3, "group", false);
1975 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1976 final NotificationRecord newGroup = generateNotificationRecord(
1977 mTestNotificationChannel, 4, "group2", false);
1978 mService.addNotification(parent);
1979 mService.addNotification(child);
1980 mService.addNotification(child2);
1981 mService.addNotification(newGroup);
1982 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1983 parent.getUserId());
1984 waitForIdle();
1985 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001986 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001987 assertEquals(1, notifs.length);
1988 }
1989
1990 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001991 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001992 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001993 mService.setPreferencesHelper(mPreferencesHelper);
1994 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001995 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001996 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001997
Julia Reynoldsbad42972017-04-25 13:52:49 -04001998 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001999 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04002000 generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002001 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
2002 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002003 }
2004
2005 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002006 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002007 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002008 mService.setPreferencesHelper(mPreferencesHelper);
2009 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002010 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05002011 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002012
Julia Reynoldsbad42972017-04-25 13:52:49 -04002013 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002014 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
2015 0, generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002016 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
Julia Reynolds0f767342019-12-18 09:11:55 -05002017 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002018 anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002019 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002020
2021 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002022 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002023 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002024
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002025 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002026 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2027 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2028
2029 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2030 captor.getValue().getAction());
2031 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002032 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2033 }
2034
2035 @Test
2036 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
2037 mService.setPreferencesHelper(mPreferencesHelper);
2038
2039 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
2040 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002041 }
2042
2043 @Test
2044 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002045 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002046
2047 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
2048 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2049 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2050
2051 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2052 captor.getValue().getAction());
2053 assertEquals(PKG, captor.getValue().getPackage());
2054 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2055 }
2056
2057 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002058 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002059 mService.setPreferencesHelper(mPreferencesHelper);
2060 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002061 eq(mTestNotificationChannel.getId()), anyBoolean()))
2062 .thenReturn(mTestNotificationChannel);
2063
2064 NotificationChannel updatedChannel =
2065 new NotificationChannel(mTestNotificationChannel.getId(),
2066 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
2067
2068 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
2069 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2070 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2071
2072 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2073 captor.getValue().getAction());
2074 assertEquals(PKG, captor.getValue().getPackage());
2075 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002076 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002077 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2078 }
2079
2080 @Test
2081 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
2082 NotificationChannel existingChannel =
2083 new NotificationChannel(mTestNotificationChannel.getId(),
2084 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002085 mService.setPreferencesHelper(mPreferencesHelper);
2086 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002087 eq(mTestNotificationChannel.getId()), anyBoolean()))
2088 .thenReturn(existingChannel);
2089
2090 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2091 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2092 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2093
2094 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2095 captor.getValue().getAction());
2096 assertEquals(PKG, captor.getValue().getPackage());
2097 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002098 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002099 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2100 }
2101
2102 @Test
2103 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
2104 NotificationChannel existingChannel =
2105 new NotificationChannel(mTestNotificationChannel.getId(),
2106 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002107 mService.setPreferencesHelper(mPreferencesHelper);
2108 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002109 eq(mTestNotificationChannel.getId()), anyBoolean()))
2110 .thenReturn(existingChannel);
2111
2112 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2113 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2114 }
2115
2116 @Test
2117 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
2118 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002119 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002120 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2121 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002122 .thenReturn(existing);
2123
2124 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
2125 updated.setBlocked(true);
2126
2127 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
2128 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2129 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2130
2131 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2132 captor.getValue().getAction());
2133 assertEquals(PKG, captor.getValue().getPackage());
2134 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002135 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002136 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2137 }
2138
2139 @Test
2140 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
2141 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2142 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002143 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002144 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2145 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002146 .thenReturn(existing);
2147
2148 mBinderService.updateNotificationChannelGroupForPackage(
2149 PKG, 0, new NotificationChannelGroup("id", "name"));
2150 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2151 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2152
2153 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2154 captor.getValue().getAction());
2155 assertEquals(PKG, captor.getValue().getPackage());
2156 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002157 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002158 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2159 }
2160
2161 @Test
2162 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
2163 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002164 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002165 when(mPreferencesHelper.getNotificationChannelGroup(
2166 eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002167 .thenReturn(existing);
2168
2169 mBinderService.updateNotificationChannelGroupForPackage(
2170 PKG, 0, new NotificationChannelGroup("id", "new name"));
2171 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2172 }
2173
2174 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002175 public void testCreateChannelNotifyListener() throws Exception {
2176 List<String> associations = new ArrayList<>();
2177 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002178 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002179 mService.setPreferencesHelper(mPreferencesHelper);
2180 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002181 eq(mTestNotificationChannel.getId()), anyBoolean()))
2182 .thenReturn(mTestNotificationChannel);
2183 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002184 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002185 eq(channel2.getId()), anyBoolean()))
2186 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002187 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
2188 eq(channel2), anyBoolean(), anyBoolean()))
2189 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002190
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002191 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002192 mBinderService.createNotificationChannels(PKG,
2193 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002194 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002195 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002196 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002197 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002198 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002199 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2200 }
2201
2202 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002203 public void testCreateChannelGroupNotifyListener() throws Exception {
2204 List<String> associations = new ArrayList<>();
2205 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002206 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002207 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002208 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
2209 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
2210
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002211 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002212 mBinderService.createNotificationChannelGroups(PKG,
2213 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002214 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002215 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002216 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002217 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002218 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002219 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2220 }
2221
2222 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002223 public void testUpdateChannelNotifyListener() throws Exception {
2224 List<String> associations = new ArrayList<>();
2225 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002226 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002227 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002228 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002229 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002230 eq(mTestNotificationChannel.getId()), anyBoolean()))
2231 .thenReturn(mTestNotificationChannel);
2232
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002233 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002234 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002235 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002236 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002237 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2238 }
2239
2240 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002241 public void testDeleteChannelNotifyListener() throws Exception {
2242 List<String> associations = new ArrayList<>();
2243 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002244 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002245 mService.setPreferencesHelper(mPreferencesHelper);
2246 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002247 eq(mTestNotificationChannel.getId()), anyBoolean()))
2248 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002249 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002250 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002251 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002252 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002253 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2254 }
2255
2256 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002257 public void testDeleteChannelGroupNotifyListener() throws Exception {
2258 List<String> associations = new ArrayList<>();
2259 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002260 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002261 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002262 mService.setPreferencesHelper(mPreferencesHelper);
2263 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002264 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002265 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002266 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002267 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002268 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002269 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2270 }
2271
2272 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002273 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002274 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002275 List<String> associations = new ArrayList<>();
2276 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002277 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002278 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002279 eq(mTestNotificationChannel.getId()), anyBoolean()))
2280 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002281
2282 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002283 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002284
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002285 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002286 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002287
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002288 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002289 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002290 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2291 }
2292
2293 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002294 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002295 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002296 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002297 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002298
2299 try {
2300 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002301 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002302 fail("listeners that don't have a companion device shouldn't be able to call this");
2303 } catch (SecurityException e) {
2304 // pass
2305 }
2306
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002307 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002308 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002309
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002310 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002311 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2312 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2313 }
2314
2315 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002316 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002317 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002318 List<String> associations = new ArrayList<>();
2319 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002320 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002321 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002322 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002323 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002324 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002325
2326 try {
2327 mBinderService.updateNotificationChannelFromPrivilegedListener(
2328 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2329 fail("incorrectly allowed a change to a user listener cannot see");
2330 } catch (SecurityException e) {
2331 // pass
2332 }
2333
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002334 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002335 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002336
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002337 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002338 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002339 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2340 }
2341
2342 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002343 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002344 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002345 List<String> associations = new ArrayList<>();
2346 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002347 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002348
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002349 mBinderService.getNotificationChannelsFromPrivilegedListener(
2350 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002351
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002352 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002353 anyString(), anyInt(), anyBoolean());
2354 }
2355
2356 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002357 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002358 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002359 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002360 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002361
2362 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002363 mBinderService.getNotificationChannelsFromPrivilegedListener(
2364 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002365 fail("listeners that don't have a companion device shouldn't be able to call this");
2366 } catch (SecurityException e) {
2367 // pass
2368 }
2369
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002370 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002371 anyString(), anyInt(), anyBoolean());
2372 }
2373
2374 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002375 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2376 throws Exception {
2377 mService.setPreferencesHelper(mPreferencesHelper);
2378 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2379 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2380
2381 mBinderService.getNotificationChannelsFromPrivilegedListener(
2382 null, PKG, Process.myUserHandle());
2383
2384 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2385 anyString(), anyInt(), anyBoolean());
2386 }
2387
2388 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002389 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2390 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002391 mService.setPreferencesHelper(mPreferencesHelper);
2392 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2393 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2394
2395 try {
2396 mBinderService.getNotificationChannelsFromPrivilegedListener(
2397 null, PKG, Process.myUserHandle());
2398 fail("listeners that don't have a companion device shouldn't be able to call this");
2399 } catch (SecurityException e) {
2400 // pass
2401 }
2402
2403 verify(mPreferencesHelper, never()).getNotificationChannels(
2404 anyString(), anyInt(), anyBoolean());
2405 }
2406
2407 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002408 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002409 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002410 List<String> associations = new ArrayList<>();
2411 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002412 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002413 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2414 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002415 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002416
2417 try {
2418 mBinderService.getNotificationChannelsFromPrivilegedListener(
2419 null, PKG, Process.myUserHandle());
2420 fail("listener getting channels from a user they cannot see");
2421 } catch (SecurityException e) {
2422 // pass
2423 }
2424
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002425 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002426 anyString(), anyInt(), anyBoolean());
2427 }
2428
2429 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002430 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002431 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002432 List<String> associations = new ArrayList<>();
2433 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002434 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002435
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002436 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2437 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002438
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002439 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002440 }
2441
2442 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002443 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002444 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002445 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002446 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002447
2448 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002449 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2450 null, PKG, Process.myUserHandle());
2451 fail("listeners that don't have a companion device shouldn't be able to call this");
2452 } catch (SecurityException e) {
2453 // pass
2454 }
2455
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002456 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002457 }
2458
2459 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002460 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002461 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002462 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002463 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002464 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2465 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002466 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002467 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002468 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2469 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002470 fail("listeners that don't have a companion device shouldn't be able to call this");
2471 } catch (SecurityException e) {
2472 // pass
2473 }
2474
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002475 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002476 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002477
2478 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002479 public void testHasCompanionDevice_failure() throws Exception {
2480 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2481 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002482 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002483 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002484
2485 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002486 public void testHasCompanionDevice_noService() {
Will Brockmancfd98302020-01-29 15:57:30 -05002487 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
2488 mNotificationInstanceIdSequence);
Julia Reynolds727a7282017-04-13 10:54:01 -04002489
Julia Reynolds503ed942017-10-04 16:04:56 -04002490 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002491 }
2492
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002493 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002494 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2495 final NotificationRecord notification = generateNotificationRecord(
2496 mTestNotificationChannel, 1, null, true);
2497 mService.addNotification(notification);
2498 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2499
2500 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2501 mService.new SnoozeNotificationRunnable(
2502 notification.getKey(), 100, null);
2503 snoozeNotificationRunnable.run();
2504 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2505 mService.new SnoozeNotificationRunnable(
2506 notification.getKey(), 100, null);
2507 snoozeNotificationRunnable.run();
2508
2509 // snooze twice
2510 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2511 }
2512
2513 @Test
2514 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2515 final NotificationRecord notification = generateNotificationRecord(
2516 mTestNotificationChannel, 1, "group", true);
2517 mService.addNotification(notification);
2518 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2519
2520 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2521 mService.new SnoozeNotificationRunnable(
2522 notification.getKey(), 100, null);
2523 snoozeNotificationRunnable.run();
2524 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2525 mService.new SnoozeNotificationRunnable(
2526 notification.getKey(), 100, null);
2527 snoozeNotificationRunnable.run();
2528
2529 // snooze twice
2530 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2531 }
2532
2533 @Test
2534 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2535 final NotificationRecord notification = generateNotificationRecord(
2536 mTestNotificationChannel, 1, "group", true);
2537 final NotificationRecord notification2 = generateNotificationRecord(
2538 mTestNotificationChannel, 2, "group", true);
2539 mService.addNotification(notification);
2540 mService.addNotification(notification2);
2541 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2542 when(mSnoozeHelper.getNotifications(
2543 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2544
2545 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2546 mService.new SnoozeNotificationRunnable(
2547 notification.getKey(), 100, null);
2548 snoozeNotificationRunnable.run();
2549 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2550 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2551 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2552 mService.new SnoozeNotificationRunnable(
2553 notification.getKey(), 100, null);
2554 snoozeNotificationRunnable.run();
2555
2556 // snooze twice
2557 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2558 }
2559
2560 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002561 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2562 final NotificationRecord nonGrouped = generateNotificationRecord(
2563 mTestNotificationChannel, 1, null, false);
2564 final NotificationRecord grouped = generateNotificationRecord(
2565 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002566 mService.addNotification(grouped);
2567 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002568
2569 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002570 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002571 nonGrouped.getKey(), 100, null);
2572 snoozeNotificationRunnable.run();
2573
2574 // only snooze the one notification
2575 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002576 assertTrue(nonGrouped.getStats().hasSnoozed());
Will Brockman9918db92020-03-06 16:48:39 -05002577
2578 assertEquals(2, mNotificationRecordLogger.numCalls());
2579 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2580 mNotificationRecordLogger.event(0));
2581 assertEquals(
2582 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2583 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002584 }
2585
2586 @Test
2587 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2588 final NotificationRecord parent = generateNotificationRecord(
2589 mTestNotificationChannel, 1, "group", true);
2590 final NotificationRecord child = generateNotificationRecord(
2591 mTestNotificationChannel, 2, "group", false);
2592 final NotificationRecord child2 = generateNotificationRecord(
2593 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002594 mService.addNotification(parent);
2595 mService.addNotification(child);
2596 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002597
2598 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002599 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002600 parent.getKey(), 100, null);
2601 snoozeNotificationRunnable.run();
2602
2603 // snooze parent and children
2604 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2605 }
2606
2607 @Test
2608 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2609 final NotificationRecord parent = generateNotificationRecord(
2610 mTestNotificationChannel, 1, "group", true);
2611 final NotificationRecord child = generateNotificationRecord(
2612 mTestNotificationChannel, 2, "group", false);
2613 final NotificationRecord child2 = generateNotificationRecord(
2614 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002615 mService.addNotification(parent);
2616 mService.addNotification(child);
2617 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002618
2619 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002620 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002621 child2.getKey(), 100, null);
2622 snoozeNotificationRunnable.run();
2623
2624 // only snooze the one child
2625 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002626
2627 assertEquals(2, mNotificationRecordLogger.numCalls());
2628 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2629 mNotificationRecordLogger.event(0));
2630 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
2631 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002632 }
2633
2634 @Test
2635 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2636 final NotificationRecord parent = generateNotificationRecord(
2637 mTestNotificationChannel, 1, "group", true);
Julia Reynolds24edc002020-01-29 16:35:32 -05002638 assertTrue(parent.getSbn().getNotification().isGroupSummary());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002639 final NotificationRecord child = generateNotificationRecord(
2640 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002641 mService.addNotification(parent);
2642 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002643
2644 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002645 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002646 child.getKey(), 100, null);
2647 snoozeNotificationRunnable.run();
2648
2649 // snooze child and summary
2650 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002651
2652 assertEquals(4, mNotificationRecordLogger.numCalls());
2653 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2654 mNotificationRecordLogger.event(0));
2655 assertEquals(
2656 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2657 mNotificationRecordLogger.event(1));
2658 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2659 mNotificationRecordLogger.event(2));
2660 assertEquals(
2661 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2662 mNotificationRecordLogger.event(3));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002663 }
2664
2665 @Test
2666 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2667 final NotificationRecord child = generateNotificationRecord(
2668 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002669 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002670
2671 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002672 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002673 child.getKey(), 100, null);
2674 snoozeNotificationRunnable.run();
2675
2676 // snooze child only
2677 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002678
2679 assertEquals(2, mNotificationRecordLogger.numCalls());
2680 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2681 mNotificationRecordLogger.event(0));
2682 assertEquals(
2683 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2684 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002685 }
2686
2687 @Test
2688 public void testPostGroupChild_unsnoozeParent() throws Exception {
2689 final NotificationRecord child = generateNotificationRecord(
2690 mTestNotificationChannel, 2, "group", false);
2691
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002692 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002693 child.getSbn().getId(), child.getSbn().getNotification(),
2694 child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002695 waitForIdle();
2696
2697 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2698 anyString(), anyInt(), eq(child.getGroupKey()));
2699 }
2700
2701 @Test
2702 public void testPostNonGroup_noUnsnoozing() throws Exception {
2703 final NotificationRecord record = generateNotificationRecord(
2704 mTestNotificationChannel, 2, null, false);
2705
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002706 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002707 record.getSbn().getId(), record.getSbn().getNotification(),
2708 record.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002709 waitForIdle();
2710
2711 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2712 }
2713
2714 @Test
2715 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2716 final NotificationRecord parent = generateNotificationRecord(
2717 mTestNotificationChannel, 2, "group", true);
2718
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002719 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002720 parent.getSbn().getId(), parent.getSbn().getNotification(),
2721 parent.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002722 waitForIdle();
2723
2724 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2725 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002726
2727 @Test
Julia Reynolds0d073782020-02-13 16:07:52 -05002728 public void testSystemNotificationListenerCanUnsnooze() throws Exception {
2729 final NotificationRecord nr = generateNotificationRecord(
2730 mTestNotificationChannel, 2, "group", false);
2731
2732 mBinderService.enqueueNotificationWithTag(PKG, PKG,
2733 "testSystemNotificationListenerCanUnsnooze",
2734 nr.getSbn().getId(), nr.getSbn().getNotification(),
2735 nr.getSbn().getUserId());
2736 waitForIdle();
2737 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2738 mService.new SnoozeNotificationRunnable(
2739 nr.getKey(), 100, null);
2740 snoozeNotificationRunnable.run();
2741
2742 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
2743 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
2744 listener.isSystem = true;
2745 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
2746
2747 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
2748 waitForIdle();
2749 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
2750 assertEquals(1, notifs.length);
2751 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
2752 }
2753
2754 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002755 public void testSetListenerAccessForUser() throws Exception {
2756 UserHandle user = UserHandle.of(10);
2757 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002758 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2759
Julia Reynolds92febc32017-10-26 11:30:31 -04002760
2761 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2762 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2763 c.flattenToString(), user.getIdentifier(), true, true);
2764 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2765 c.flattenToString(), user.getIdentifier(), false, true);
2766 verify(mAssistants, never()).setPackageOrComponentEnabled(
2767 any(), anyInt(), anyBoolean(), anyBoolean());
2768 }
2769
2770 @Test
2771 public void testSetAssistantAccessForUser() throws Exception {
2772 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002773 List<UserInfo> uis = new ArrayList<>();
2774 UserInfo ui = new UserInfo();
2775 ui.id = 10;
2776 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002777 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002778 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2779
2780 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002781
2782 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2783 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2784 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002785 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002786 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2787 c.flattenToString(), user.getIdentifier(), false, true);
2788 verify(mListeners, never()).setPackageOrComponentEnabled(
2789 any(), anyInt(), anyBoolean(), anyBoolean());
2790 }
2791
2792 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002793 public void testGetAssistantAllowedForUser() throws Exception {
2794 UserHandle user = UserHandle.of(10);
2795 try {
2796 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2797 } catch (IllegalStateException e) {
2798 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2799 throw e;
2800 }
2801 }
2802 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2803 }
2804
2805 @Test
2806 public void testGetAssistantAllowed() throws Exception {
2807 try {
2808 mBinderService.getAllowedNotificationAssistant();
2809 } catch (IllegalStateException e) {
2810 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2811 throw e;
2812 }
2813 }
2814 verify(mAssistants, times(1)).getAllowedComponents(0);
2815 }
2816
2817 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002818 public void testSetDndAccessForUser() throws Exception {
2819 UserHandle user = UserHandle.of(10);
2820 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002821 mBinderService.setNotificationPolicyAccessGrantedForUser(
2822 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002823
2824 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2825 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2826 c.getPackageName(), user.getIdentifier(), true, true);
2827 verify(mAssistants, never()).setPackageOrComponentEnabled(
2828 any(), anyInt(), anyBoolean(), anyBoolean());
2829 verify(mListeners, never()).setPackageOrComponentEnabled(
2830 any(), anyInt(), anyBoolean(), anyBoolean());
2831 }
2832
2833 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002834 public void testSetListenerAccess() throws Exception {
2835 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002836 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002837
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002838 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002839 c.flattenToString(), 0, true, true);
2840 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2841 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002842 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002843 any(), anyInt(), anyBoolean(), anyBoolean());
2844 }
2845
2846 @Test
2847 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002848 List<UserInfo> uis = new ArrayList<>();
2849 UserInfo ui = new UserInfo();
2850 ui.id = 0;
2851 uis.add(ui);
2852 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002853 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002854
2855 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002856
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002857 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002858 c.flattenToString(), 0, true, true);
2859 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2860 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002861 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002862 any(), anyInt(), anyBoolean(), anyBoolean());
2863 }
2864
2865 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002866 public void testSetAssistantAccess_multiProfile() throws Exception {
2867 List<UserInfo> uis = new ArrayList<>();
2868 UserInfo ui = new UserInfo();
2869 ui.id = 0;
2870 uis.add(ui);
2871 UserInfo ui10 = new UserInfo();
2872 ui10.id = 10;
2873 uis.add(ui10);
2874 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2875 ComponentName c = ComponentName.unflattenFromString("package/Component");
2876
2877 mBinderService.setNotificationAssistantAccessGranted(c, true);
2878
2879 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2880 c.flattenToString(), 0, true, true);
2881 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2882 c.flattenToString(), 10, true, true);
2883 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2884 c.flattenToString(), 0, false, true);
2885 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2886 c.flattenToString(), 10, false, true);
2887 verify(mListeners, never()).setPackageOrComponentEnabled(
2888 any(), anyInt(), anyBoolean(), anyBoolean());
2889 }
2890
2891 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002892 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2893 ArrayList<ComponentName> componentList = new ArrayList<>();
2894 ComponentName c = ComponentName.unflattenFromString("package/Component");
2895 componentList.add(c);
2896 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002897 List<UserInfo> uis = new ArrayList<>();
2898 UserInfo ui = new UserInfo();
2899 ui.id = 0;
2900 uis.add(ui);
2901 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002902
Julia Reynolds4afe2642019-05-01 08:42:24 -04002903 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002904
2905 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2906 c.flattenToString(), 0, true, false);
2907 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2908 c.flattenToString(), 0, false, false);
2909 verify(mListeners, never()).setPackageOrComponentEnabled(
2910 any(), anyInt(), anyBoolean(), anyBoolean());
2911 }
2912
2913 @Test
2914 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002915 List<UserInfo> uis = new ArrayList<>();
2916 UserInfo ui = new UserInfo();
2917 ui.id = 10;
2918 uis.add(ui);
2919 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002920 ArrayList<ComponentName> componentList = new ArrayList<>();
2921 ComponentName c = ComponentName.unflattenFromString("package/Component");
2922 componentList.add(c);
2923 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002924 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002925
Julia Reynolds4afe2642019-05-01 08:42:24 -04002926 mBinderService.setNotificationAssistantAccessGrantedForUser(
2927 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002928
2929 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2930 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002931 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002932 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2933 c.flattenToString(), user.getIdentifier(), false, false);
2934 verify(mListeners, never()).setPackageOrComponentEnabled(
2935 any(), anyInt(), anyBoolean(), anyBoolean());
2936 }
2937
2938 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002939 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2940 throws Exception {
2941 List<UserInfo> uis = new ArrayList<>();
2942 UserInfo ui = new UserInfo();
2943 ui.id = 0;
2944 uis.add(ui);
2945 UserInfo ui10 = new UserInfo();
2946 ui10.id = 10;
2947 uis.add(ui10);
2948 UserHandle user = ui.getUserHandle();
2949 ArrayList<ComponentName> componentList = new ArrayList<>();
2950 ComponentName c = ComponentName.unflattenFromString("package/Component");
2951 componentList.add(c);
2952 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2953 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2954
2955 mBinderService.setNotificationAssistantAccessGrantedForUser(
2956 null, user.getIdentifier(), true);
2957
2958 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2959 c.flattenToString(), user.getIdentifier(), true, false);
2960 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2961 c.flattenToString(), ui10.id, true, false);
2962 verify(mAssistants).setUserSet(0, true);
2963 verify(mAssistants).setUserSet(10, true);
2964 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2965 c.flattenToString(), user.getIdentifier(), false, false);
2966 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2967 c.flattenToString(), ui10.id, false, false);
2968 verify(mListeners, never()).setPackageOrComponentEnabled(
2969 any(), anyInt(), anyBoolean(), anyBoolean());
2970 }
2971
2972 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002973 public void testSetDndAccess() throws Exception {
2974 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002975
2976 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002977
2978 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2979 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002980 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002981 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002982 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002983 any(), anyInt(), anyBoolean(), anyBoolean());
2984 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002985
2986 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002987 public void testSetListenerAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04002988 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2989 ComponentName c = ComponentName.unflattenFromString("package/Component");
2990 mBinderService.setNotificationListenerAccessGranted(c, true);
2991
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002992 verify(mListeners).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002993 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002994 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002995 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08002996 verify(mAssistants).migrateToXml();
2997 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04002998 }
2999
3000 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003001 public void testSetAssistantAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003002 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3003 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003004 List<UserInfo> uis = new ArrayList<>();
3005 UserInfo ui = new UserInfo();
3006 ui.id = 0;
3007 uis.add(ui);
3008 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3009
Julia Reynolds68263d12017-06-21 14:21:19 -04003010 mBinderService.setNotificationAssistantAccessGranted(c, true);
3011
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003012 verify(mListeners).migrateToXml();
3013 verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
3014 anyInt());
3015 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003016 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003017 verify(mAssistants).migrateToXml();
3018 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04003019 }
3020
3021 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003022 public void testSetDndAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003023 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3024 ComponentName c = ComponentName.unflattenFromString("package/Component");
3025 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3026
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003027 verify(mListeners).migrateToXml();
3028 verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
3029 anyInt());
3030 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003031 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003032 verify(mAssistants).migrateToXml();
3033 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynoldse1816412017-10-24 10:39:11 -04003034 }
3035
3036 @Test
3037 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3038 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3039 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3040 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003041
3042 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003043
3044 verify(mListeners, times(1)).setPackageOrComponentEnabled(
3045 c.flattenToString(), 0, true, true);
3046 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003047 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003048 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003049 any(), anyInt(), anyBoolean(), anyBoolean());
3050 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04003051
3052 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04003053 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3054 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3055 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3056 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003057 List<UserInfo> uis = new ArrayList<>();
3058 UserInfo ui = new UserInfo();
3059 ui.id = 0;
3060 uis.add(ui);
3061 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3062
3063 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003064
3065 verify(mListeners, never()).setPackageOrComponentEnabled(
3066 anyString(), anyInt(), anyBoolean(), anyBoolean());
3067 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3068 c.flattenToString(), 0, false, true);
3069 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3070 c.flattenToString(), 0, true, true);
3071 }
3072
3073 @Test
3074 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3075 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3076 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3077 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003078
3079 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003080
3081 verify(mListeners, never()).setPackageOrComponentEnabled(
3082 anyString(), anyInt(), anyBoolean(), anyBoolean());
3083 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3084 c.getPackageName(), 0, true, true);
3085 verify(mAssistants, never()).setPackageOrComponentEnabled(
3086 any(), anyInt(), anyBoolean(), anyBoolean());
3087 }
3088
3089 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04003090 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
3091 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003092 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003093 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003094 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003095 runnable.run();
3096 waitForIdle();
3097
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003098 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003099 }
3100
3101 @Test
3102 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
3103 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003104 NotificationRecord r =
3105 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003106 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003107
3108 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003109 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003110 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003111 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003112 runnable.run();
3113 waitForIdle();
3114
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003115 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003116 }
3117
3118 @Test
3119 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
3120 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04003121 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
3122 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003123 mService.addNotification(r);
3124 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003125
3126 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003127 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003128 runnable.run();
3129 waitForIdle();
3130
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003131 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003132 }
Beverly40239d92017-07-07 10:20:41 -04003133
Julia Reynolds4db59552017-06-30 13:34:01 -04003134 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07003135 public void testDontAutogroupIfCritical() throws Exception {
3136 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3137 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
3138 mService.addEnqueuedNotification(r);
3139 NotificationManagerService.PostNotificationRunnable runnable =
3140 mService.new PostNotificationRunnable(r.getKey());
3141 runnable.run();
3142
3143 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
3144 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
3145 runnable = mService.new PostNotificationRunnable(r.getKey());
3146 mService.addEnqueuedNotification(r);
3147
3148 runnable.run();
3149 waitForIdle();
3150
3151 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
3152 }
3153
3154 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04003155 public void testNoFakeColorizedPermission() throws Exception {
3156 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
3157 Notification.Builder nb = new Notification.Builder(mContext,
3158 mTestNotificationChannel.getId())
3159 .setContentTitle("foo")
3160 .setColorized(true)
3161 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
3162 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003163 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
3164 "testNoFakeColorizedPermission", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003165 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04003166 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3167
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003168 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds24edc002020-01-29 16:35:32 -05003169 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003170 waitForIdle();
3171
Julia Reynolds503ed942017-10-04 16:04:56 -04003172 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003173 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003174
3175 assertFalse(posted.getNotification().isColorized());
3176 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003177
3178 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003179 public void testGetNotificationCountLocked() {
3180 String sampleTagToExclude = null;
3181 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003182 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003183 NotificationRecord r =
3184 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003185 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003186
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003187 }
3188 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003189 NotificationRecord r =
3190 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003191 mService.addNotification(r);
Julia Reynolds24edc002020-01-29 16:35:32 -05003192 sampleTagToExclude = r.getSbn().getTag();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003193 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003194 }
3195
3196 // another package
3197 Notification n =
3198 new Notification.Builder(mContext, mTestNotificationChannel.getId())
3199 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3200 .build();
3201
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003202 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
3203 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003204 NotificationRecord otherPackage =
3205 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003206 mService.addEnqueuedNotification(otherPackage);
3207 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003208
3209 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003210 // anything that's currently enqueued or posted
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003211 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003212 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003213 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003214 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003215 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003216
3217 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003218 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04003219 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003220
3221 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003222 assertEquals(39, mService.getNotificationCountLocked(
3223 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003224 }
3225
3226 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04003227 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003228 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003229 mService.addNotification(r);
3230 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003231
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003232 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003233 }
3234
3235 @Test
3236 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003237 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3238 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003239 mService.addNotification(r);
3240 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003241
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003242 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003243 }
3244
3245 @Test
3246 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003247 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3248 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003249 mService.addNotification(r);
3250 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003251
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003252 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003253 }
3254
3255 @Test
3256 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04003257 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003258 NotificationManagerService.WorkerHandler handler = mock(
3259 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003260 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003261
3262 Map<String, Answer> answers = getSignalExtractorSideEffects();
3263 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04003264 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003265 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003266 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003267
3268 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
3269
Julia Reynolds503ed942017-10-04 16:04:56 -04003270 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003271 }
3272 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
3273 }
3274
3275 @Test
3276 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003277 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003278 NotificationManagerService.WorkerHandler handler = mock(
3279 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003280 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003281
3282 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003283 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003284
Julia Reynolds503ed942017-10-04 16:04:56 -04003285 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003286 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003287 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003288
3289 @Test
3290 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04003291 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003292 + "<ranking></ranking>"
3293 + "<enabled_listeners>"
3294 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3295 + "</enabled_listeners>"
3296 + "<enabled_assistants>"
3297 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3298 + "</enabled_assistants>"
3299 + "<dnd_apps>"
3300 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3301 + "</dnd_apps>"
3302 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003303 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003304 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3305 false,
3306 UserHandle.USER_ALL);
3307 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3308 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3309 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003310
3311 // numbers are inflated for setup
3312 verify(mListeners, times(1)).migrateToXml();
3313 verify(mConditionProviders, times(1)).migrateToXml();
3314 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003315 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003316 }
3317
3318 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003319 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
3320 final String upgradeXml = "<notification-policy version=\"1\">"
3321 + "<snoozed-notifications>></snoozed-notifications>"
3322 + "</notification-policy>";
3323 mService.readPolicyXml(
3324 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3325 false,
3326 UserHandle.USER_ALL);
Julia Reynolds9050d9a2020-02-20 09:38:05 -05003327 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong());
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003328 }
3329
3330 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003331 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
3332 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003333 + "<ranking></ranking>"
3334 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003335 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003336 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
3337 false,
3338 UserHandle.USER_ALL);
3339 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
3340 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
3341 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003342
3343 // numbers are inflated for setup
3344 verify(mListeners, times(2)).migrateToXml();
3345 verify(mConditionProviders, times(2)).migrateToXml();
3346 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003347 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003348 }
3349
Annie Meng8b646fd2019-02-01 18:46:42 +00003350 @Test
3351 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3352 final String policyXml = "<notification-policy version=\"1\">"
3353 + "<ranking></ranking>"
3354 + "<enabled_listeners>"
3355 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3356 + "</enabled_listeners>"
3357 + "<enabled_assistants>"
3358 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3359 + "</enabled_assistants>"
3360 + "<dnd_apps>"
3361 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3362 + "</dnd_apps>"
3363 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003364 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00003365 mService.readPolicyXml(
3366 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3367 true,
3368 10);
3369 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3370 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3371 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3372 }
3373
3374 @Test
3375 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3376 final String policyXml = "<notification-policy version=\"1\">"
3377 + "<ranking></ranking>"
3378 + "<enabled_listeners>"
3379 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3380 + "</enabled_listeners>"
3381 + "<enabled_assistants>"
3382 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3383 + "</enabled_assistants>"
3384 + "<dnd_apps>"
3385 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3386 + "</dnd_apps>"
3387 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003388 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003389 mService.readPolicyXml(
3390 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3391 true,
3392 10);
3393 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3394 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3395 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3396 }
Beverlyd4f96492017-08-02 13:36:11 -04003397
3398 @Test
3399 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3400 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003401 mService.mZenModeHelper = mZenModeHelper;
3402 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003403 new Intent(Intent.ACTION_LOCALE_CHANGED));
3404
3405 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3406 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003407
3408 @Test
3409 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003410 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003411 final ApplicationInfo legacy = new ApplicationInfo();
3412 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3413 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3414 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003415 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3416 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003417 getContext().setMockPackageManager(mPackageManagerClient);
3418
3419 Notification.Builder nb = new Notification.Builder(mContext,
3420 NotificationChannel.DEFAULT_CHANNEL_ID)
3421 .setContentTitle("foo")
3422 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003423 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003424 .setPriority(Notification.PRIORITY_MIN);
3425
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003426 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3427 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds24edc002020-01-29 16:35:32 -05003428 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null,
3429 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003430
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003431 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3432 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003433 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003434
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003435 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003436 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003437
3438 nb = new Notification.Builder(mContext)
3439 .setContentTitle("foo")
3440 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003441 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003442 .setPriority(Notification.PRIORITY_MIN);
3443
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003444 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3445 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003446 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003447
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003448 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3449 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003450 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3451 waitForIdle();
3452 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003453 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003454
3455 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003456 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003457 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3458 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003459
3460 @Test
3461 public void testStats_updatedOnDirectReply() throws Exception {
3462 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3463 mService.addNotification(r);
3464
3465 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3466 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Julia Reynolds24edc002020-01-29 16:35:32 -05003467 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.getSbn()));
Will Brockman9918db92020-03-06 16:48:39 -05003468
3469 assertEquals(1, mNotificationRecordLogger.numCalls());
3470 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
3471 mNotificationRecordLogger.event(0));
Julia Reynolds503ed942017-10-04 16:04:56 -04003472 }
3473
3474 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003475 public void testStats_updatedOnUserExpansion() throws Exception {
3476 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003477 mService.addNotification(r);
3478
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003479 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3480 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003481 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3482 eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003483 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003484
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003485 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3486 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003487 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3488 eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003489 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Will Brockman9918db92020-03-06 16:48:39 -05003490
3491 assertEquals(2, mNotificationRecordLogger.numCalls());
3492 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
3493 mNotificationRecordLogger.event(0));
3494 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
3495 mNotificationRecordLogger.event(1));
Julia Reynolds503ed942017-10-04 16:04:56 -04003496 }
3497
3498 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003499 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3500 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3501 mService.addNotification(r);
3502
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003503 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3504 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003505 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Julia Reynolds24edc002020-01-29 16:35:32 -05003506 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(false),
3507 eq((true)));
Tony Makeda84a72018-11-19 17:01:32 +00003508
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003509 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3510 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003511 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003512 verify(mAssistants).notifyAssistantExpansionChangedLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003513 eq(r.getSbn()), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003514 }
3515
3516 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003517 public void testStats_updatedOnViewSettings() throws Exception {
3518 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3519 mService.addNotification(r);
3520
3521 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3522 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3523 }
3524
3525 @Test
3526 public void testStats_updatedOnVisibilityChanged() throws Exception {
3527 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3528 mService.addNotification(r);
3529
Dieter Hsud39f0d52018-04-14 02:08:30 +08003530 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003531 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3532 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
Julia Reynolds24edc002020-01-29 16:35:32 -05003533 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(true));
Julia Reynolds503ed942017-10-04 16:04:56 -04003534 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3535 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3536 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
Julia Reynolds24edc002020-01-29 16:35:32 -05003537 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(false));
Julia Reynolds503ed942017-10-04 16:04:56 -04003538 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3539 }
3540
3541 @Test
3542 public void testStats_dismissalSurface() throws Exception {
3543 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Will Brockman4f0f9d22020-02-23 21:18:11 -05003544 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003545 mService.addNotification(r);
3546
Dieter Hsud39f0d52018-04-14 02:08:30 +08003547 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003548 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3549 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003550 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003551 waitForIdle();
3552
3553 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
Will Brockman75c60572020-01-31 10:30:27 -05003554
3555 // Using mService.addNotification() does not generate a NotificationRecordLogger log,
3556 // so we only get the cancel notification.
Will Brockman9918db92020-03-06 16:48:39 -05003557 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockman75c60572020-01-31 10:30:27 -05003558
Will Brockman75c60572020-01-31 10:30:27 -05003559 assertEquals(
3560 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
Will Brockman9918db92020-03-06 16:48:39 -05003561 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05003562 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003563 }
3564
3565 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003566 public void testStats_dismissalSentiment() throws Exception {
3567 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3568 mService.addNotification(r);
3569
3570 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003571 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3572 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003573 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3574 waitForIdle();
3575
3576 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3577 r.getStats().getDismissalSentiment());
3578 }
3579
3580 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003581 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003582 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3583 mService.addNotification(r);
3584 NotificationManagerService.WorkerHandler handler = mock(
3585 NotificationManagerService.WorkerHandler.class);
3586 mService.setHandler(handler);
3587
Julia Reynolds70aaea72018-07-13 13:38:34 -04003588 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3589
Julia Reynolds503ed942017-10-04 16:04:56 -04003590 Bundle signals = new Bundle();
3591 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003592 USER_SENTIMENT_NEGATIVE);
3593 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003594 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003595 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3596
3597 waitForIdle();
3598
3599 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3600 }
3601
3602 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003603 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003604 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3605 mService.addNotification(r);
3606 NotificationManagerService.WorkerHandler handler = mock(
3607 NotificationManagerService.WorkerHandler.class);
3608 mService.setHandler(handler);
3609
3610 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003611 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003612 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003613 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003614 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3615 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3616
3617 waitForIdle();
3618
3619 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3620 verify(handler, times(1)).scheduleCancelNotification(any());
3621 }
3622
3623 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003624 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3625 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3626 mService.addEnqueuedNotification(r);
3627 NotificationManagerService.WorkerHandler handler = mock(
3628 NotificationManagerService.WorkerHandler.class);
3629 mService.setHandler(handler);
3630 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3631
3632 Bundle signals = new Bundle();
3633 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3634 USER_SENTIMENT_NEGATIVE);
3635 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003636 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003637 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3638
3639 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3640 }
3641
3642 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003643 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003644 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3645 mService.addEnqueuedNotification(r);
3646 NotificationManagerService.WorkerHandler handler = mock(
3647 NotificationManagerService.WorkerHandler.class);
3648 mService.setHandler(handler);
3649 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3650
3651 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003652 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003653 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003654 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05003655 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3656
3657 assertEquals(IMPORTANCE_LOW, r.getImportance());
3658 }
3659
3660 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003661 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3662 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3663 mService.addEnqueuedNotification(r);
3664 NotificationManagerService.WorkerHandler handler = mock(
3665 NotificationManagerService.WorkerHandler.class);
3666 mService.setHandler(handler);
3667 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3668
3669 Bundle signals = new Bundle();
3670 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3671 USER_SENTIMENT_NEGATIVE);
3672 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003673 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003674 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3675
3676 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3677
3678 waitForIdle();
3679
3680 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3681 }
3682
3683 @Test
3684 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3685 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3686 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003687 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3688
3689 Bundle signals = new Bundle();
3690 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3691 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003692 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003693 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds503ed942017-10-04 16:04:56 -04003694 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3695
3696 waitForIdle();
3697
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003698 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003699 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003700
3701 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003702 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3703 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3704 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003705 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003706
3707 Bundle signals = new Bundle();
3708 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003709 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003710 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003711 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003712 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3713
3714 waitForIdle();
3715
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003716 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003717 }
3718
3719 @Test
3720 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3721 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3722 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003723 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003724
3725 Bundle signals = new Bundle();
3726 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003727 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003728 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003729 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003730 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3731
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003732 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003733 }
3734
3735 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003736 public void testRestore() throws Exception {
3737 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003738 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003739 assertEquals(1, mService.countSystemChecks - systemChecks);
3740 }
3741
3742 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003743 public void testBackupEmptySound() throws Exception {
3744 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3745 channel.setSound(Uri.EMPTY, null);
3746
3747 XmlSerializer serializer = new FastXmlSerializer();
3748 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3749 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3750 channel.writeXmlForBackup(serializer, getContext());
3751
3752 XmlPullParser parser = Xml.newPullParser();
3753 parser.setInput(new BufferedInputStream(
3754 new ByteArrayInputStream(baos.toByteArray())), null);
3755 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3756 restored.populateFromXmlForRestore(parser, getContext());
3757
3758 assertNull(restored.getSound());
3759 }
3760
3761 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003762 public void testBackup() throws Exception {
3763 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04003764 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3765 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003766 mBinderService.getBackupPayload(1);
3767 assertEquals(1, mService.countSystemChecks - systemChecks);
3768 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003769
3770 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003771 public void testEmptyVibration_noException() throws Exception {
3772 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3773 channel.setVibrationPattern(new long[0]);
3774
3775 XmlSerializer serializer = new FastXmlSerializer();
3776 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3777 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3778 channel.writeXml(serializer);
3779 }
3780
3781 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003782 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003783 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003784 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003785 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3786 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003787 message1.setData("",
3788 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003789 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003790 message2.setData("",
3791 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003792
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003793 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003794 .setContentTitle("foo")
3795 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3796 .setStyle(new Notification.MessagingStyle("")
3797 .addMessage(message1)
3798 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003799 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3800 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003801
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003802 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003803 reset(mUgm);
3804 reset(mUgmInternal);
3805 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003806 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003807 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003808 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003809 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003810 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003811 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3812
3813 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003814 .setContentTitle("foo")
3815 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3816 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003817 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3818 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003819
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003820 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003821 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003822 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003823 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003824 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3825 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003826
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003827 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003828 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003829 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003830 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003831 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003832 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003833
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003834 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003835 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003836 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003837 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003838 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003839 anyInt(), anyInt());
3840 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003841
3842 @Test
Julia Reynoldsea58c202020-02-03 12:52:49 -05003843 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
3844 NotificationChannel c = new NotificationChannel(
3845 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
3846 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3847 Message message1 = new Message("", 0, "");
3848 message1.setData("",
3849 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
3850
3851 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
3852 .setContentTitle("foo")
3853 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3854 .setStyle(new Notification.MessagingStyle("")
3855 .addMessage(message1));
3856 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3857 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
3858
3859 doThrow(new SecurityException("no access")).when(mUgm)
3860 .grantUriPermissionFromOwner(
3861 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
3862
3863 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
3864 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM);
3865
3866 // yay, no crash
3867 }
3868
3869 @Test
Robin Leed107af62018-04-27 13:55:56 +02003870 public void testVisitUris() throws Exception {
3871 final Uri audioContents = Uri.parse("content://com.example/audio");
3872 final Uri backgroundImage = Uri.parse("content://com.example/background");
3873
3874 Bundle extras = new Bundle();
3875 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3876 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3877
3878 Notification n = new Notification.Builder(mContext, "a")
3879 .setContentTitle("notification with uris")
3880 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3881 .addExtras(extras)
3882 .build();
3883
3884 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3885 n.visitUris(visitor);
3886 verify(visitor, times(1)).accept(eq(audioContents));
3887 verify(visitor, times(1)).accept(eq(backgroundImage));
3888 }
3889
3890 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003891 public void testSetNotificationPolicy_preP_setOldFields() {
3892 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3893 mService.mZenModeHelper = mZenModeHelper;
3894 NotificationManager.Policy userPolicy =
3895 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3896 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3897
3898 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3899 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3900
3901 int expected = SUPPRESSED_EFFECT_BADGE
3902 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003903 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3904 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003905 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3906
3907 assertEquals(expected, actual);
3908 }
3909
3910 @Test
3911 public void testSetNotificationPolicy_preP_setNewFields() {
3912 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3913 mService.mZenModeHelper = mZenModeHelper;
3914 NotificationManager.Policy userPolicy =
3915 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3916 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3917
3918 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3919 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3920
3921 int expected = SUPPRESSED_EFFECT_BADGE;
3922 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3923
3924 assertEquals(expected, actual);
3925 }
3926
3927 @Test
3928 public void testSetNotificationPolicy_preP_setOldNewFields() {
3929 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3930 mService.mZenModeHelper = mZenModeHelper;
3931 NotificationManager.Policy userPolicy =
3932 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3933 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3934
3935 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3936 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3937
3938 int expected =
3939 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3940 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3941
3942 assertEquals(expected, actual);
3943 }
3944
3945 @Test
3946 public void testSetNotificationPolicy_P_setOldFields() {
3947 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3948 mService.mZenModeHelper = mZenModeHelper;
3949 NotificationManager.Policy userPolicy =
3950 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3951 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3952
3953 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3954 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3955
3956 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3957 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3958 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3959 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3960
3961 assertEquals(expected, actual);
3962 }
3963
3964 @Test
3965 public void testSetNotificationPolicy_P_setNewFields() {
3966 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3967 mService.mZenModeHelper = mZenModeHelper;
3968 NotificationManager.Policy userPolicy =
3969 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3970 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3971
3972 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3973 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3974 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3975
3976 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3977 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3978 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3979 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3980
3981 assertEquals(expected, actual);
3982 }
3983
3984 @Test
3985 public void testSetNotificationPolicy_P_setOldNewFields() {
3986 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3987 mService.mZenModeHelper = mZenModeHelper;
3988 NotificationManager.Policy userPolicy =
3989 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3990 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3991
3992 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3993 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3994
3995 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3996 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3997
3998 assertEquals(expected, actual);
3999
4000 appPolicy = new NotificationManager.Policy(0, 0, 0,
4001 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
4002 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4003
4004 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
4005 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4006 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4007
4008 assertEquals(expected, actual);
4009 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05004010
4011 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04004012 public void testVisualDifference_foreground() {
4013 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4014 .setContentTitle("foo");
4015 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4016 nb1.build(), new UserHandle(mUid), null, 0);
4017 NotificationRecord r1 =
4018 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4019
4020 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4021 .setFlag(FLAG_FOREGROUND_SERVICE, true)
4022 .setContentTitle("bar");
4023 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4024 nb2.build(), new UserHandle(mUid), null, 0);
4025 NotificationRecord r2 =
4026 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4027
4028 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4029 }
4030
4031 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004032 public void testVisualDifference_diffTitle() {
4033 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4034 .setContentTitle("foo");
4035 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4036 nb1.build(), new UserHandle(mUid), null, 0);
4037 NotificationRecord r1 =
4038 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4039
4040 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4041 .setContentTitle("bar");
4042 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4043 nb2.build(), new UserHandle(mUid), null, 0);
4044 NotificationRecord r2 =
4045 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4046
4047 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4048 }
4049
4050 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004051 public void testVisualDifference_inboxStyle() {
4052 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4053 .setStyle(new Notification.InboxStyle()
4054 .addLine("line1").addLine("line2"));
4055 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4056 nb1.build(), new UserHandle(mUid), null, 0);
4057 NotificationRecord r1 =
4058 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4059
4060 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4061 .setStyle(new Notification.InboxStyle()
4062 .addLine("line1").addLine("line2_changed"));
4063 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4064 nb2.build(), new UserHandle(mUid), null, 0);
4065 NotificationRecord r2 =
4066 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4067
4068 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
4069
4070 Notification.Builder nb3 = new Notification.Builder(mContext, "")
4071 .setStyle(new Notification.InboxStyle()
4072 .addLine("line1"));
4073 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4074 nb3.build(), new UserHandle(mUid), null, 0);
4075 NotificationRecord r3 =
4076 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
4077
4078 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
4079
4080 Notification.Builder nb4 = new Notification.Builder(mContext, "")
4081 .setStyle(new Notification.InboxStyle()
4082 .addLine("line1").addLine("line2").addLine("line3"));
4083 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4084 nb4.build(), new UserHandle(mUid), null, 0);
4085 NotificationRecord r4 =
4086 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
4087
4088 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
4089
4090 Notification.Builder nb5 = new Notification.Builder(mContext, "")
4091 .setContentText("not an inbox");
4092 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4093 nb5.build(), new UserHandle(mUid), null, 0);
4094 NotificationRecord r5 =
4095 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
4096
4097 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
4098 }
4099
4100 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004101 public void testVisualDifference_diffText() {
4102 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4103 .setContentText("foo");
4104 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4105 nb1.build(), new UserHandle(mUid), null, 0);
4106 NotificationRecord r1 =
4107 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4108
4109 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4110 .setContentText("bar");
4111 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4112 nb2.build(), new UserHandle(mUid), null, 0);
4113 NotificationRecord r2 =
4114 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4115
4116 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4117 }
4118
4119 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004120 public void testVisualDifference_sameText() {
4121 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4122 .setContentText("foo");
4123 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4124 nb1.build(), new UserHandle(mUid), null, 0);
4125 NotificationRecord r1 =
4126 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4127
4128 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4129 .setContentText("foo");
4130 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4131 nb2.build(), new UserHandle(mUid), null, 0);
4132 NotificationRecord r2 =
4133 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4134
4135 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4136 }
4137
4138 @Test
4139 public void testVisualDifference_sameTextButStyled() {
4140 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4141 .setContentText(Html.fromHtml("<b>foo</b>"));
4142 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4143 nb1.build(), new UserHandle(mUid), null, 0);
4144 NotificationRecord r1 =
4145 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4146
4147 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4148 .setContentText(Html.fromHtml("<b>foo</b>"));
4149 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4150 nb2.build(), new UserHandle(mUid), null, 0);
4151 NotificationRecord r2 =
4152 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4153
4154 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4155 }
4156
4157 @Test
4158 public void testVisualDifference_diffTextButStyled() {
4159 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4160 .setContentText(Html.fromHtml("<b>foo</b>"));
4161 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4162 nb1.build(), new UserHandle(mUid), null, 0);
4163 NotificationRecord r1 =
4164 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4165
4166 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4167 .setContentText(Html.fromHtml("<b>bar</b>"));
4168 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4169 nb2.build(), new UserHandle(mUid), null, 0);
4170 NotificationRecord r2 =
4171 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4172
4173 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4174 }
4175
4176 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004177 public void testVisualDifference_diffProgress() {
4178 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4179 .setProgress(100, 90, false);
4180 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4181 nb1.build(), new UserHandle(mUid), null, 0);
4182 NotificationRecord r1 =
4183 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4184
4185 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4186 .setProgress(100, 100, false);
4187 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4188 nb2.build(), new UserHandle(mUid), null, 0);
4189 NotificationRecord r2 =
4190 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4191
4192 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4193 }
4194
4195 @Test
4196 public void testVisualDifference_diffProgressNotDone() {
4197 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4198 .setProgress(100, 90, false);
4199 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4200 nb1.build(), new UserHandle(mUid), null, 0);
4201 NotificationRecord r1 =
4202 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4203
4204 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4205 .setProgress(100, 91, false);
4206 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4207 nb2.build(), new UserHandle(mUid), null, 0);
4208 NotificationRecord r2 =
4209 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4210
4211 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4212 }
Beverly5a20a5e2018-03-06 15:02:44 -05004213
4214 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004215 public void testVisualDifference_sameProgressStillDone() {
4216 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4217 .setProgress(100, 100, false);
4218 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4219 nb1.build(), new UserHandle(mUid), null, 0);
4220 NotificationRecord r1 =
4221 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4222
4223 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4224 .setProgress(100, 100, false);
4225 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4226 nb2.build(), new UserHandle(mUid), null, 0);
4227 NotificationRecord r2 =
4228 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4229
4230 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4231 }
4232
4233 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004234 public void testVisualDifference_summary() {
4235 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4236 .setGroup("bananas")
4237 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4238 .setContentText("foo");
4239 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4240 nb1.build(), new UserHandle(mUid), null, 0);
4241 NotificationRecord r1 =
4242 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4243
4244 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4245 .setGroup("bananas")
4246 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4247 .setContentText("bar");
4248 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4249 nb2.build(), new UserHandle(mUid), null, 0);
4250 NotificationRecord r2 =
4251 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4252
4253 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4254 }
4255
4256 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04004257 public void testVisualDifference_summaryNewNotification() {
4258 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4259 .setGroup("bananas")
4260 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4261 .setContentText("bar");
4262 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
4263 nb2.build(), new UserHandle(mUid), null, 0);
4264 NotificationRecord r2 =
4265 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4266
4267 assertFalse(mService.isVisuallyInterruptive(null, r2));
4268 }
4269
4270 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05004271 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
4272 // post 2 notification from this package
4273 final NotificationRecord notif1 = generateNotificationRecord(
4274 mTestNotificationChannel, 1, null, true);
4275 final NotificationRecord notif2 = generateNotificationRecord(
4276 mTestNotificationChannel, 2, null, false);
4277 mService.addNotification(notif1);
4278 mService.addNotification(notif2);
4279
4280 // on broadcast, hide the 2 notifications
4281 mService.simulatePackageSuspendBroadcast(true, PKG);
4282 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
4283 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4284 assertEquals(2, captorHide.getValue().size());
4285
4286 // on broadcast, unhide the 2 notifications
4287 mService.simulatePackageSuspendBroadcast(false, PKG);
4288 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
4289 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4290 assertEquals(2, captorUnhide.getValue().size());
4291 }
4292
4293 @Test
4294 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
4295 // post 2 notification from this package
4296 final NotificationRecord notif1 = generateNotificationRecord(
4297 mTestNotificationChannel, 1, null, true);
4298 final NotificationRecord notif2 = generateNotificationRecord(
4299 mTestNotificationChannel, 2, null, false);
4300 mService.addNotification(notif1);
4301 mService.addNotification(notif2);
4302
4303 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4304 mService.simulatePackageSuspendBroadcast(true, "test_package");
4305 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4306 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4307 assertEquals(0, captor.getValue().size());
4308 }
Kristian Monsen05f34792018-04-09 10:27:16 +02004309
4310 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004311 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
4312 // Post 2 notifications from 2 packages
4313 NotificationRecord pkgA = new NotificationRecord(mContext,
4314 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4315 mService.addNotification(pkgA);
4316 NotificationRecord pkgB = new NotificationRecord(mContext,
4317 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4318 mService.addNotification(pkgB);
4319
4320 // on broadcast, hide one of the packages
4321 mService.simulatePackageDistractionBroadcast(
4322 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
4323 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4324 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4325 assertEquals(1, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004326 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004327
4328 // on broadcast, unhide the package
4329 mService.simulatePackageDistractionBroadcast(
4330 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
4331 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4332 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4333 assertEquals(1, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004334 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004335 }
4336
4337 @Test
4338 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
4339 // Post 2 notifications from 2 packages
4340 NotificationRecord pkgA = new NotificationRecord(mContext,
4341 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4342 mService.addNotification(pkgA);
4343 NotificationRecord pkgB = new NotificationRecord(mContext,
4344 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4345 mService.addNotification(pkgB);
4346
4347 // on broadcast, hide one of the packages
4348 mService.simulatePackageDistractionBroadcast(
4349 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
4350 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004351
4352 // should be called only once.
4353 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004354 assertEquals(2, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004355 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
4356 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004357
4358 // on broadcast, unhide the package
4359 mService.simulatePackageDistractionBroadcast(
4360 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
4361 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004362
4363 // should be called only once.
4364 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004365 assertEquals(2, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004366 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
4367 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004368 }
4369
4370 @Test
4371 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
4372 // post notification from this package
4373 final NotificationRecord notif1 = generateNotificationRecord(
4374 mTestNotificationChannel, 1, null, true);
4375 mService.addNotification(notif1);
4376
4377 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4378 mService.simulatePackageDistractionBroadcast(
4379 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
4380 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4381 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4382 assertEquals(0, captor.getValue().size());
4383 }
4384
4385 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004386 public void testCanUseManagedServicesNullPkg() {
4387 assertEquals(true, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004388 }
4389
Kristian Monsen05f34792018-04-09 10:27:16 +02004390
4391 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004392 public void testCanUseManagedServicesNoValidPkg() {
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004393 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4394 }
4395
4396 @Test
4397 public void testCanUseManagedServices_hasPermission() throws Exception {
4398 when(mPackageManager.checkPermission("perm", "pkg", 0))
4399 .thenReturn(PackageManager.PERMISSION_GRANTED);
4400
4401 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4402 }
4403
4404 @Test
4405 public void testCanUseManagedServices_noPermission() throws Exception {
4406 when(mPackageManager.checkPermission("perm", "pkg", 0))
4407 .thenReturn(PackageManager.PERMISSION_DENIED);
4408
4409 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4410 }
4411
4412 @Test
4413 public void testCanUseManagedServices_permDoesNotMatter() {
4414 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004415 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004416
4417 @Test
4418 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4419 final NotificationRecord r = generateNotificationRecord(
4420 mTestNotificationChannel, 1, null, true);
4421 r.setTextChanged(true);
4422 mService.addNotification(r);
4423
4424 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4425 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4426 new NotificationVisibility[]{});
4427
4428 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4429 }
4430
4431 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05004432 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
4433 final NotificationRecord r = generateNotificationRecord(
4434 mTestNotificationChannel, 1, null, true);
4435 r.setTextChanged(true);
Will Brockman4f0f9d22020-02-23 21:18:11 -05004436 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004437 mService.addNotification(r);
4438
4439 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4440 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4441 new NotificationVisibility[]{});
4442
Will Brockman9918db92020-03-06 16:48:39 -05004443 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004444 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
Will Brockman9918db92020-03-06 16:48:39 -05004445 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004446 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004447
4448 mService.mNotificationDelegate.onNotificationVisibilityChanged(
4449 new NotificationVisibility[]{},
4450 new NotificationVisibility[]
4451 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
4452 );
4453
Will Brockman9918db92020-03-06 16:48:39 -05004454 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004455 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
Will Brockman9918db92020-03-06 16:48:39 -05004456 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004457 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004458 }
4459
4460 @Test
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004461 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4462 throws RemoteException {
4463 final NotificationRecord r = generateNotificationRecord(
4464 mTestNotificationChannel, 1, null, true);
4465 r.setTextChanged(true);
4466 mService.addNotification(r);
4467
4468 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4469
4470 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4471 }
4472
4473 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004474 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004475 throws RemoteException {
4476 final NotificationRecord r = generateNotificationRecord(
4477 mTestNotificationChannel, 1, null, true);
4478 r.setInterruptive(true);
4479 mService.addNotification(r);
4480
4481 mService.maybeRecordInterruptionLocked(r);
4482 mService.maybeRecordInterruptionLocked(r);
4483
4484 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4485 anyString(), anyString(), anyInt());
Julia Reynoldsfd9f8342020-03-06 09:36:00 -05004486 verify(mHistoryManager, times(1)).addNotification(any());
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004487 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004488
4489 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004490 public void testBubble() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004491 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4492 assertFalse(mBinderService.areBubblesAllowed(PKG));
4493 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4494 BUBBLE_PREFERENCE_NONE);
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004495 }
4496
4497 @Test
Mady Mellora92268c2020-03-09 17:25:08 -07004498 public void testUserApprovedBubblesForPackageSelected() throws Exception {
4499 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
4500 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4501 BUBBLE_PREFERENCE_SELECTED);
4502 }
4503
4504 @Test
4505 public void testUserApprovedBubblesForPackageAll() throws Exception {
4506 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
4507 assertTrue(mBinderService.areBubblesAllowed(PKG));
4508 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4509 BUBBLE_PREFERENCE_ALL);
Mady Mellor9db685a2019-01-23 13:23:37 -08004510 }
4511
4512 @Test
4513 public void testUserRejectsBubblesForPackage() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004514 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4515 assertFalse(mBinderService.areBubblesAllowed(PKG));
Mady Mellor9db685a2019-01-23 13:23:37 -08004516 }
4517
4518 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004519 public void testIsCallerInstantApp_primaryUser() throws Exception {
4520 ApplicationInfo info = new ApplicationInfo();
4521 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4522 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004523 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004524
Julia Reynolds268647a2018-10-25 16:54:27 -04004525 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004526
4527 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004528 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004529 }
4530
4531 @Test
4532 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4533 ApplicationInfo info = new ApplicationInfo();
4534 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4535 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4536 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004537 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004538
Julia Reynolds268647a2018-10-25 16:54:27 -04004539 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004540 }
4541
4542 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004543 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4544 ApplicationInfo info = new ApplicationInfo();
4545 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004546 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004547 .thenReturn(info);
4548 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4549
4550 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4551
4552 info.privateFlags = 0;
4553 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4554 }
4555
4556 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004557 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4558 ApplicationInfo info = new ApplicationInfo();
4559 info.uid = Binder.getCallingUid();
4560 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4561 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4562
4563 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4564
4565 assertEquals(info.uid, actualUid);
4566 }
4567
4568 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004569 public void testResolveNotificationUid_sameApp() throws Exception {
4570 ApplicationInfo info = new ApplicationInfo();
4571 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004572 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004573
4574 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4575
4576 assertEquals(info.uid, actualUid);
4577 }
4578
4579 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004580 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004581 ApplicationInfo info = new ApplicationInfo();
4582 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004583 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004584
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004585 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4586
4587 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004588 }
4589
4590 @Test
4591 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4592 ApplicationInfo info = new ApplicationInfo();
4593 info.uid = 1356347;
4594 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4595
4596 try {
4597 mService.resolveNotificationUid("caller", "caller", 9, 0);
4598 fail("Incorrect uid didn't throw security exception");
4599 } catch (SecurityException e) {
4600 // yay
4601 }
4602 }
4603
4604 @Test
4605 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4606 int expectedUid = 123;
4607
4608 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4609 mService.setPreferencesHelper(mPreferencesHelper);
4610 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4611 .thenReturn(true);
4612
4613 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4614 }
4615
4616 @Test
4617 public void testResolveNotificationUid_androidAllowed() throws Exception {
4618 int expectedUid = 123;
4619
4620 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4621 // no delegate
4622
4623 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4624 }
4625
4626 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004627 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4628 final String notReal = "NOT REAL";
4629 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4630 PackageManager.NameNotFoundException.class);
4631 ApplicationInfo ai = new ApplicationInfo();
4632 ai.uid = -1;
4633 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4634
Julia Reynolds24edc002020-01-29 16:35:32 -05004635 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004636 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004637 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4638 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004639 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4640 fail("can't post notifications for nonexistent packages, even if you exist");
4641 } catch (SecurityException e) {
4642 // yay
4643 }
4644 }
4645
4646 @Test
4647 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4648 final String notReal = "NOT REAL";
4649 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4650 PackageManager.NameNotFoundException.class);
4651 ApplicationInfo ai = new ApplicationInfo();
4652 ai.uid = -1;
4653 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4654
4655 // unlike the post case, ignore instead of throwing
Julia Reynolds24edc002020-01-29 16:35:32 -05004656 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004657
4658 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4659 sbn.getId(), sbn.getUserId());
4660 }
4661
4662 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004663 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4664 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4665 // no delegate
4666
4667 try {
4668 mService.resolveNotificationUid("caller", "target", 9, 0);
4669 fail("Incorrect uid didn't throw security exception");
4670 } catch (SecurityException e) {
4671 // yay
4672 }
4673 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004674
4675 @Test
4676 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4677 Notification n = new Notification.Builder(mContext, "").build();
4678 n.flags |= FLAG_FOREGROUND_SERVICE;
4679
4680 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4681 n, new UserHandle(mUid), null, 0);
4682 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4683
4684 mService.addEnqueuedNotification(r);
4685
4686 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004687 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004688
4689 waitForIdle();
4690
4691 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4692 }
4693
4694 @Test
4695 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4696 Notification n = new Notification.Builder(mContext, "").build();
4697 n.flags |= FLAG_FOREGROUND_SERVICE;
4698
4699 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4700 n, new UserHandle(mUid), null, 0);
4701 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4702
4703 mService.addNotification(r);
4704
4705 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004706 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004707
4708 waitForIdle();
4709
4710 ArgumentCaptor<NotificationRecord> captor =
4711 ArgumentCaptor.forClass(NotificationRecord.class);
4712 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4713
4714 assertEquals(0, captor.getValue().getNotification().flags);
4715 }
Beverly58b24532018-10-02 09:08:23 -04004716
4717 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004718 public void testAllowForegroundCustomToasts() throws Exception {
Beverly58b24532018-10-02 09:08:23 -04004719 final String testPackage = "testPackageName";
4720 assertEquals(0, mService.mToastQueue.size());
4721 mService.isSystemUid = false;
4722
4723 // package is not suspended
4724 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4725 .thenReturn(false);
4726
4727 // notifications from this package are blocked by the user
4728 mService.setPreferencesHelper(mPreferencesHelper);
4729 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4730
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004731 setAppInForegroundForToasts(mUid, true);
Beverly58b24532018-10-02 09:08:23 -04004732
4733 // enqueue toast -> toast should still enqueue
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004734 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004735 new TestableToastCallback(), 2000, 0);
4736 assertEquals(1, mService.mToastQueue.size());
4737 }
4738
4739 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004740 public void testDisallowBackgroundCustomToasts() throws Exception {
4741 final String testPackage = "testPackageName";
4742 assertEquals(0, mService.mToastQueue.size());
4743 mService.isSystemUid = false;
4744
4745 // package is not suspended
4746 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4747 .thenReturn(false);
4748
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004749 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004750
4751 // enqueue toast -> no toasts enqueued
4752 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
4753 new TestableToastCallback(), 2000, 0);
4754 assertEquals(0, mService.mToastQueue.size());
4755 }
4756
4757 @Test
4758 public void testAllowForegroundTextToasts() throws Exception {
4759 final String testPackage = "testPackageName";
4760 assertEquals(0, mService.mToastQueue.size());
4761 mService.isSystemUid = false;
4762
4763 // package is not suspended
4764 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4765 .thenReturn(false);
4766
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004767 setAppInForegroundForToasts(mUid, true);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004768
4769 // enqueue toast -> toast should still enqueue
4770 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4771 "Text", 2000, 0, null);
4772 assertEquals(1, mService.mToastQueue.size());
4773 }
4774
4775 @Test
4776 public void testAllowBackgroundTextToasts() throws Exception {
4777 final String testPackage = "testPackageName";
4778 assertEquals(0, mService.mToastQueue.size());
4779 mService.isSystemUid = false;
4780
4781 // package is not suspended
4782 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4783 .thenReturn(false);
4784
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004785 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004786
4787 // enqueue toast -> toast should still enqueue
4788 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4789 "Text", 2000, 0, null);
4790 assertEquals(1, mService.mToastQueue.size());
4791 }
4792
4793 @Test
4794 public void testTextToastsCallStatusBar() throws Exception {
4795 final String testPackage = "testPackageName";
4796 assertEquals(0, mService.mToastQueue.size());
4797 mService.isSystemUid = false;
4798
4799 // package is not suspended
4800 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4801 .thenReturn(false);
4802
4803 // enqueue toast -> no toasts enqueued
4804 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4805 "Text", 2000, 0, null);
Bernardo Rufino78f5d832020-04-03 11:50:23 +01004806 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
Bernardo Rufino18725b62020-01-21 14:12:43 +00004807 }
4808
4809 @Test
Beverly58b24532018-10-02 09:08:23 -04004810 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4811 final String testPackage = "testPackageName";
4812 assertEquals(0, mService.mToastQueue.size());
4813 mService.isSystemUid = false;
4814
4815 // package is suspended
4816 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4817 .thenReturn(true);
4818
4819 // notifications from this package are NOT blocked by the user
4820 mService.setPreferencesHelper(mPreferencesHelper);
4821 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4822
4823 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004824 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004825 new TestableToastCallback(), 2000, 0);
4826 assertEquals(0, mService.mToastQueue.size());
4827 }
4828
4829 @Test
4830 public void testDisallowToastsFromBlockedApps() throws Exception {
4831 final String testPackage = "testPackageName";
4832 assertEquals(0, mService.mToastQueue.size());
4833 mService.isSystemUid = false;
4834
4835 // package is not suspended
4836 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4837 .thenReturn(false);
4838
4839 // notifications from this package are blocked by the user
4840 mService.setPreferencesHelper(mPreferencesHelper);
4841 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4842
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004843 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04004844
4845 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004846 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004847 new TestableToastCallback(), 2000, 0);
4848 assertEquals(0, mService.mToastQueue.size());
4849 }
4850
4851 @Test
4852 public void testAlwaysAllowSystemToasts() throws Exception {
4853 final String testPackage = "testPackageName";
4854 assertEquals(0, mService.mToastQueue.size());
4855 mService.isSystemUid = true;
4856
4857 // package is suspended
4858 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4859 .thenReturn(true);
4860
4861 // notifications from this package ARE blocked by the user
4862 mService.setPreferencesHelper(mPreferencesHelper);
4863 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4864
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004865 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04004866
4867 // enqueue toast -> system toast can still be enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004868 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004869 new TestableToastCallback(), 2000, 0);
4870 assertEquals(1, mService.mToastQueue.size());
4871 }
Tony Mak29996702018-11-26 16:23:34 +00004872
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004873 private void setAppInForegroundForToasts(int uid, boolean inForeground) {
4874 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
4875 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
4876 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
4877 }
4878
Tony Mak29996702018-11-26 16:23:34 +00004879 @Test
Alex Mang509e5542020-01-03 13:06:40 -08004880 public void testOnPanelRevealedAndHidden() {
4881 int items = 5;
4882 mService.mNotificationDelegate.onPanelRevealed(false, items);
4883 verify(mAssistants, times(1)).onPanelRevealed(eq(items));
4884
4885 mService.mNotificationDelegate.onPanelHidden();
4886 verify(mAssistants, times(1)).onPanelHidden();
Will Brockman9918db92020-03-06 16:48:39 -05004887
4888 assertEquals(2, mNotificationRecordLogger.numCalls());
4889 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
4890 mNotificationRecordLogger.event(0));
4891 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
4892 mNotificationRecordLogger.event(1));
Alex Mang509e5542020-01-03 13:06:40 -08004893 }
4894
4895 @Test
Tony Mak29996702018-11-26 16:23:34 +00004896 public void testOnNotificationSmartReplySent() {
4897 final int replyIndex = 2;
4898 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004899 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004900 final boolean generatedByAssistant = true;
4901
4902 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004903 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004904 mService.addNotification(r);
4905
4906 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004907 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4908 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004909 verify(mAssistants).notifyAssistantSuggestedReplySent(
Julia Reynolds24edc002020-01-29 16:35:32 -05004910 eq(r.getSbn()), eq(reply), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05004911 assertEquals(1, mNotificationRecordLogger.numCalls());
4912 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
4913 mNotificationRecordLogger.event(0));
Tony Mak29996702018-11-26 16:23:34 +00004914 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004915
4916 @Test
4917 public void testOnNotificationActionClick() {
4918 final int actionIndex = 2;
4919 final Notification.Action action =
4920 new Notification.Action.Builder(null, "text", null).build();
4921 final boolean generatedByAssistant = false;
4922
4923 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4924 mService.addNotification(r);
4925
4926 NotificationVisibility notificationVisibility =
4927 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4928 mService.mNotificationDelegate.onNotificationActionClick(
4929 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4930 generatedByAssistant);
4931 verify(mAssistants).notifyAssistantActionClicked(
Julia Reynolds24edc002020-01-29 16:35:32 -05004932 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05004933
4934 assertEquals(1, mNotificationRecordLogger.numCalls());
4935 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED,
4936 mNotificationRecordLogger.event(0));
Tony Mak7d4b3a52018-11-27 17:29:36 +00004937 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004938
4939 @Test
4940 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4941 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4942 mService.addNotification(r);
4943
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004944 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4945 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004946 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4947 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4948 };
4949 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4950 new NotificationVisibility[0]);
4951
4952 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4953 }
4954
4955 @Test
4956 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4957 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4958 mService.addNotification(r);
4959
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004960 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4961 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004962
4963 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4964 }
4965
4966 @Test
4967 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4968 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4969 mService.addNotification(r);
4970
Julia Reynolds95334132018-12-19 11:15:35 -05004971 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004972 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4973 };
4974 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4975 new NotificationVisibility[0]);
4976
4977 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4978 }
Julia Reynolds95334132018-12-19 11:15:35 -05004979
Colin Cross5ea7fb72019-12-18 17:16:36 -08004980 @Test
Julia Reynolds95334132018-12-19 11:15:35 -05004981 public void testReportSeen_delegated() {
4982 Notification.Builder nb =
4983 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4984 .setContentTitle("foo")
4985 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4986
4987 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4988 nb.build(), new UserHandle(mUid), null, 0);
4989 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4990
4991 mService.reportSeen(r);
4992 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4993
4994 }
4995
4996 @Test
4997 public void testReportSeen_notDelegated() {
4998 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4999
5000 mService.reportSeen(r);
5001 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
5002 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005003
5004 @Test
5005 public void testNotificationStats_notificationError() {
5006 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5007 mService.addNotification(r);
5008
Julia Reynolds24edc002020-01-29 16:35:32 -05005009 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
5010 r.getSbn().getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005011 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
5012 new UserHandle(mUid), null, 0);
5013 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5014 mService.addEnqueuedNotification(update);
Julia Reynolds24edc002020-01-29 16:35:32 -05005015 assertNull(update.getSbn().getNotification().getSmallIcon());
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005016
5017 NotificationManagerService.PostNotificationRunnable runnable =
5018 mService.new PostNotificationRunnable(update.getKey());
5019 runnable.run();
5020 waitForIdle();
5021
5022 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
5023 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
5024 assertNotNull(captor.getValue());
5025 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005026
5027 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005028 public void testCanNotifyAsUser_crossUser() throws Exception {
5029 // same user no problem
5030 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
5031
5032 // cross user, no permission, problem
5033 try {
5034 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5035 fail("Should not be callable cross user without cross user permission");
5036 } catch (SecurityException e) {
5037 // good
5038 }
5039
5040 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005041 enableInteractAcrossUsers();
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005042 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5043 }
5044
5045 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005046 public void testgetNotificationChannels_crossUser() throws Exception {
5047 // same user no problem
5048 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
5049
5050 // cross user, no permission, problem
5051 try {
5052 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5053 fail("Should not be callable cross user without cross user permission");
5054 } catch (SecurityException e) {
5055 // good
5056 }
5057
5058 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005059 enableInteractAcrossUsers();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005060 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5061 }
5062
5063 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00005064 public void setDefaultAssistantForUser_fromConfigXml() {
5065 clearDeviceConfig();
5066 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04005067 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005068 when(mResources
5069 .getString(
5070 com.android.internal.R.string.config_defaultAssistantAccessComponent))
5071 .thenReturn(xmlConfig.flattenToString());
5072 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005073 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
5074 .thenReturn(components);
5075 when(mAssistants.getDefaultComponents())
5076 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00005077 mService.setNotificationAssistantAccessGrantedCallback(
5078 mNotificationAssistantAccessGrantedCallback);
5079
Jay Aliomer4204f252019-08-26 11:36:53 -04005080
Tony Mak9a3c1f12019-03-04 16:04:42 +00005081 mService.setDefaultAssistantForUser(0);
5082
5083 verify(mNotificationAssistantAccessGrantedCallback)
5084 .onGranted(eq(xmlConfig), eq(0), eq(true));
5085 }
5086
5087 @Test
5088 public void setDefaultAssistantForUser_fromDeviceConfig() {
5089 ComponentName xmlConfig = new ComponentName("xml", "config");
5090 ComponentName deviceConfig = new ComponentName("device", "config");
5091 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5092 when(mResources
5093 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5094 .thenReturn(xmlConfig.flattenToString());
5095 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005096 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00005097 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04005098 when(mAssistants.getDefaultComponents())
5099 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005100 mService.setNotificationAssistantAccessGrantedCallback(
5101 mNotificationAssistantAccessGrantedCallback);
5102
5103 mService.setDefaultAssistantForUser(0);
5104
5105 verify(mNotificationAssistantAccessGrantedCallback)
5106 .onGranted(eq(deviceConfig), eq(0), eq(true));
5107 }
5108
5109 @Test
5110 public void setDefaultAssistantForUser_deviceConfigInvalid() {
5111 ComponentName xmlConfig = new ComponentName("xml", "config");
5112 ComponentName deviceConfig = new ComponentName("device", "config");
5113 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5114 when(mResources
5115 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5116 .thenReturn(xmlConfig.flattenToString());
5117 when(mContext.getResources()).thenReturn(mResources);
5118 // Only xmlConfig is valid, deviceConfig is not.
5119 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04005120 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
5121 when(mAssistants.getDefaultComponents())
5122 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005123 mService.setNotificationAssistantAccessGrantedCallback(
5124 mNotificationAssistantAccessGrantedCallback);
5125
5126 mService.setDefaultAssistantForUser(0);
5127
5128 verify(mNotificationAssistantAccessGrantedCallback)
5129 .onGranted(eq(xmlConfig), eq(0), eq(true));
5130 }
5131
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005132 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04005133 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
5134 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
5135 generateResetComponentValues();
5136 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
5137 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5138 ComponentName deviceConfig1 = new ComponentName("device", "config1");
5139 ComponentName deviceConfig2 = new ComponentName("device", "config2");
5140 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
5141 changes.put(false, new ArrayList());
5142 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
5143 mService.getBinderService().clearData("device", 0, false);
5144 verify(mAssistants, times(1))
5145 .setPackageOrComponentEnabled(
5146 eq("device/config2"),
5147 eq(0), eq(true), eq(false));
5148 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5149 eq("device"), eq(0), eq(false), eq(true));
5150 }
5151
5152 @Test
5153 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
5154 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
5155 generateResetComponentValues();
5156 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
5157 ComponentName deviceConfig = new ComponentName("device", "config");
5158 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5159 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
5160 changes.put(false, new ArrayList());
5161 when(mListeners.resetComponents(anyString(), anyInt()))
5162 .thenReturn(changes);
5163 mService.getBinderService().clearData("device", 0, false);
5164 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5165 eq("device"), eq(0), eq(false), eq(true));
5166 }
5167
5168 @Test
5169 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
5170 ComponentName deviceConfig = new ComponentName("device", "config");
5171 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
5172 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
5173 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
5174 mService.getBinderService().clearData("device", 0, false);
5175 verify(mConditionProviders, times(1)).resetPackage(
5176 eq("device"), eq(0));
5177 }
5178
5179 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07005180 public void testFlagBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005181 setUpPrefsForBubbles(PKG, mUid,
5182 true /* global */,
5183 BUBBLE_PREFERENCE_ALL /* app */,
5184 true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07005185
Mady Mellor9e923e12019-12-17 16:08:46 -08005186 NotificationRecord nr =
5187 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
Mady Mellor65dcaa92019-04-03 12:21:44 -07005188
Julia Reynolds24edc002020-01-29 16:35:32 -05005189 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5190 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005191 waitForIdle();
5192
5193 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5194 assertEquals(1, notifs.length);
5195 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
5196 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005197 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005198 }
5199
5200 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07005201 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005202 setUpPrefsForBubbles(PKG, mUid,
5203 true /* global */,
5204 BUBBLE_PREFERENCE_NONE /* app */,
5205 true /* channel */);
Mady Mellorc6820342019-05-20 12:04:36 -07005206
Mady Mellor9e923e12019-12-17 16:08:46 -08005207 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5208 "testFlagBubble_noFlag_appNotAllowed");
Mady Mellorc6820342019-05-20 12:04:36 -07005209
Julia Reynolds24edc002020-01-29 16:35:32 -05005210 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5211 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorc6820342019-05-20 12:04:36 -07005212 waitForIdle();
5213
5214 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5215 assertEquals(1, notifs.length);
5216 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
5217 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005218 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorc6820342019-05-20 12:04:36 -07005219 }
5220
5221 @Test
Mady Mellor9e923e12019-12-17 16:08:46 -08005222 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005223 setUpPrefsForBubbles(PKG, mUid,
5224 true /* global */,
5225 BUBBLE_PREFERENCE_ALL /* app */,
5226 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005227
Mady Mellorbe797962019-04-01 16:04:24 -07005228 // Notif with bubble metadata but not our other misc requirements
Mady Mellor9e923e12019-12-17 16:08:46 -08005229 Notification.Builder nb = new Notification.Builder(mContext,
5230 mTestNotificationChannel.getId())
5231 .setContentTitle("foo")
5232 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Mady Mellora92268c2020-03-09 17:25:08 -07005233 .setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -08005234 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
5235 nb.build(), new UserHandle(mUid), null, 0);
5236 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellorbe797962019-04-01 16:04:24 -07005237
5238 // Say we're foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05005239 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellorbe797962019-04-01 16:04:24 -07005240 IMPORTANCE_FOREGROUND);
Julia Reynolds24edc002020-01-29 16:35:32 -05005241 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5242 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005243 waitForIdle();
5244
Mady Mellor9e923e12019-12-17 16:08:46 -08005245 // if notif isn't configured properly it doesn't get to bubble just because app is
5246 // foreground.
Mady Mellorbe797962019-04-01 16:04:24 -07005247 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005248 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005249 }
5250
5251 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005252 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005253 setUpPrefsForBubbles(PKG, mUid,
5254 true /* global */,
5255 BUBBLE_PREFERENCE_ALL /* app */,
5256 true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005257
Mady Mellor9e923e12019-12-17 16:08:46 -08005258 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5259 "testFlagBubbleNotifs_flag_messaging");
Mady Mellorbe797962019-04-01 16:04:24 -07005260
Julia Reynolds24edc002020-01-29 16:35:32 -05005261 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5262 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005263 waitForIdle();
5264
5265 // yes allowed, yes messaging, yes bubble
5266 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005267 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005268 }
5269
5270 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005271 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005272 setUpPrefsForBubbles(PKG, mUid,
5273 true /* global */,
5274 BUBBLE_PREFERENCE_NONE /* app */,
5275 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005276
Mady Mellor9e923e12019-12-17 16:08:46 -08005277 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5278 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005279
5280 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005281 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5282 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005283 waitForIdle();
5284
5285 // not allowed, no bubble
5286 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005287 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005288 }
5289
5290 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005291 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005292 setUpPrefsForBubbles(PKG, mUid,
5293 true /* global */,
5294 BUBBLE_PREFERENCE_ALL /* app */,
5295 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005296
Mady Mellor9e923e12019-12-17 16:08:46 -08005297 // Messaging notif WITHOUT bubble metadata
5298 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
5299 null /* groupKey */, false /* isSummary */);
5300
5301 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5302 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
5303 nb.build(), new UserHandle(mUid), null, 0);
5304 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005305
5306 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005307 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5308 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005309 waitForIdle();
5310
5311 // no bubble metadata, no bubble
5312 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005313 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005314 }
5315
5316 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005317 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005318 setUpPrefsForBubbles(PKG, mUid,
5319 true /* global */,
5320 BUBBLE_PREFERENCE_ALL /* app */,
5321 false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005322
Mady Mellor9e923e12019-12-17 16:08:46 -08005323 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5324 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
Mady Mellora92268c2020-03-09 17:25:08 -07005325 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005326
5327 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005328 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5329 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005330 waitForIdle();
5331
5332 // channel not allowed, no bubble
5333 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005334 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005335 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005336
Mady Mellor49b1bf12019-03-29 12:00:02 -07005337 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005338 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
Mady Mellor49b1bf12019-03-29 12:00:02 -07005339 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005340 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005341
5342 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005343 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5344 "testAppCancelNotifications_cancelsBubbles",
Julia Reynolds24edc002020-01-29 16:35:32 -05005345 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
5346 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005347 waitForIdle();
5348
5349 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5350 assertEquals(1, notifs.length);
5351 assertEquals(1, mService.getNotificationRecordCount());
5352
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005353 mBinderService.cancelNotificationWithTag(PKG, PKG,
Julia Reynolds24edc002020-01-29 16:35:32 -05005354 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
5355 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005356 waitForIdle();
5357
5358 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5359 assertEquals(0, notifs2.length);
5360 assertEquals(0, mService.getNotificationRecordCount());
5361 }
5362
5363 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005364 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
5365 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5366 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5367 mService.addNotification(nr);
5368
5369 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
5370 waitForIdle();
5371
5372 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5373 assertEquals(0, notifs.length);
5374 assertEquals(0, mService.getNotificationRecordCount());
5375 }
5376
5377 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005378 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5379 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5380 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005381 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005382
5383 mService.addNotification(nrNormal);
5384 mService.addNotification(nrBubble);
5385
5386 mService.getBinderService().cancelNotificationsFromListener(null, null);
5387 waitForIdle();
5388
5389 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5390 assertEquals(1, notifs.length);
5391 assertEquals(1, mService.getNotificationRecordCount());
5392 }
5393
5394 @Test
5395 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
5396 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5397 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005398 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005399
5400 mService.addNotification(nrNormal);
5401 mService.addNotification(nrBubble);
5402
Julia Reynolds24edc002020-01-29 16:35:32 -05005403 String[] keys = {nrNormal.getSbn().getKey(), nrBubble.getSbn().getKey()};
Mady Mellor49b1bf12019-03-29 12:00:02 -07005404 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5405 waitForIdle();
5406
5407 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5408 assertEquals(1, notifs.length);
5409 assertEquals(1, mService.getNotificationRecordCount());
Will Brockman9918db92020-03-06 16:48:39 -05005410
5411 assertEquals(1, mNotificationRecordLogger.numCalls());
5412 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
5413 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
Mady Mellor49b1bf12019-03-29 12:00:02 -07005414 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005415
Julia Reynolds4214da92019-04-10 15:04:06 -04005416 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005417 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
5418 // GIVEN a notification bubble
5419 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5420 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5421 mService.addNotification(nr);
5422
5423 // WHEN the status bar clears all notifications
5424 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
5425 nr.getSbn().getUserId());
5426 waitForIdle();
5427
5428 // THEN the bubble notification does not get removed
5429 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5430 assertEquals(1, notifs.length);
5431 assertEquals(1, mService.getNotificationRecordCount());
5432 }
5433
5434
5435 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005436 public void testGetAllowedAssistantAdjustments() throws Exception {
5437 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005438 assertNotNull(capabilities);
5439
5440 for (int i = capabilities.size() - 1; i >= 0; i--) {
5441 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005442 mBinderService.disallowAssistantAdjustment(capability);
5443 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5444 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005445 assertNotNull(currentCapabilities);
5446 assertFalse(currentCapabilities.contains(capability));
5447 }
5448 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005449
Julia Reynolds4214da92019-04-10 15:04:06 -04005450 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005451 public void testAdjustRestrictedKey() throws Exception {
5452 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005453 mService.addNotification(r);
5454 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005455
5456 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5457 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5458
5459 Bundle signals = new Bundle();
5460 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5461 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
Julia Reynolds24edc002020-01-29 16:35:32 -05005462 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005463 "", r.getUser().getIdentifier());
5464
5465 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5466 r.applyAdjustments();
5467
5468 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5469 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5470 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005471
Julia Reynolds4214da92019-04-10 15:04:06 -04005472 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005473 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005474 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5475 .thenReturn(true);
5476 mService.setZenHelper(mock(ZenModeHelper.class));
5477 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005478 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5479 boolean isEnabled = true;
5480 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5481 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5482
5483 try {
5484 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005485 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005486 } catch (IllegalArgumentException e) {
5487 // yay
5488 }
5489
5490 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5491 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5492 mBinderService.addAutomaticZenRule(rule);
5493
5494 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5495 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5496 mBinderService.addAutomaticZenRule(rule);
5497 }
5498
Julia Reynolds4214da92019-04-10 15:04:06 -04005499 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005500 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5501 try {
5502 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5503 mUid + UserHandle.PER_USER_RANGE);
5504 fail("Cannot call cross user without permission");
5505 } catch (SecurityException e) {
5506 // pass
5507 }
5508
5509 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005510 enableInteractAcrossUsers();
Julia Reynolds657d1642019-03-27 12:15:57 -04005511 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5512 mUid + UserHandle.PER_USER_RANGE);
5513 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005514
Julia Reynolds4214da92019-04-10 15:04:06 -04005515 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005516 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5517 try {
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 fail("Cannot call cross user without permission");
5521 } catch (SecurityException e) {
5522 // pass
5523 }
5524
5525 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005526 enableInteractAcrossUsers();
Mady Mellora92268c2020-03-09 17:25:08 -07005527 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005528 mUid + UserHandle.PER_USER_RANGE);
5529 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005530
Will Brockmancfd98302020-01-29 15:57:30 -05005531 private void enableInteractAcrossUsers() {
5532 TestablePermissions perms = mContext.getTestablePermissions();
5533 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5534 }
5535
Mady Mellora54e9fa2019-04-18 13:26:18 -07005536 @Test
5537 public void testNotificationBubbleChanged_false() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005538 setUpPrefsForBubbles(PKG, mUid,
5539 true /* global */,
5540 BUBBLE_PREFERENCE_ALL /* app */,
5541 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005542
Mady Mellor9e923e12019-12-17 16:08:46 -08005543 // Notif with bubble metadata
5544 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5545 "testNotificationBubbleChanged_false");
Mady Mellora54e9fa2019-04-18 13:26:18 -07005546
Julia Reynolds24edc002020-01-29 16:35:32 -05005547 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5548 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005549 waitForIdle();
5550
Mady Mellor66efd5e2019-05-15 13:38:11 -07005551 // Reset as this is called when the notif is first sent
5552 reset(mListeners);
5553
Mady Mellora54e9fa2019-04-18 13:26:18 -07005554 // First we were a bubble
5555 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5556 assertEquals(1, notifsBefore.length);
5557 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5558
5559 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005560 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005561 waitForIdle();
5562
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005563 // Make sure we are not a bubble
5564 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5565 assertEquals(1, notifsAfter.length);
5566 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005567 }
5568
5569 @Test
5570 public void testNotificationBubbleChanged_true() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005571 setUpPrefsForBubbles(PKG, mUid,
5572 true /* global */,
5573 BUBBLE_PREFERENCE_ALL /* app */,
5574 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005575
Mady Mellor9e923e12019-12-17 16:08:46 -08005576 // Notif that is not a bubble
Mady Mellora54e9fa2019-04-18 13:26:18 -07005577 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08005578 1, null, false);
Julia Reynolds24edc002020-01-29 16:35:32 -05005579 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5580 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005581 waitForIdle();
5582
5583 // Would be a normal notification because wouldn't have met requirements to bubble
5584 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5585 assertEquals(1, notifsBefore.length);
5586 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5587
Mady Mellor9e923e12019-12-17 16:08:46 -08005588 // Update the notification to be message style / meet bubble requirements
5589 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
Julia Reynolds24edc002020-01-29 16:35:32 -05005590 nr.getSbn().getTag());
5591 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
5592 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
Mady Mellor9e923e12019-12-17 16:08:46 -08005593 waitForIdle();
Mady Mellora54e9fa2019-04-18 13:26:18 -07005594
Mady Mellor66efd5e2019-05-15 13:38:11 -07005595 // Reset as this is called when the notif is first sent
5596 reset(mListeners);
5597
Mady Mellora54e9fa2019-04-18 13:26:18 -07005598 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005599 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005600 waitForIdle();
5601
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005602 // Make sure we are a bubble
5603 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5604 assertEquals(1, notifsAfter.length);
5605 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005606 }
5607
5608 @Test
5609 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005610 setUpPrefsForBubbles(PKG, mUid,
5611 true /* global */,
5612 BUBBLE_PREFERENCE_ALL /* app */,
5613 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005614
5615 // Notif that is not a bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005616 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005617 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5618 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005619 waitForIdle();
5620
Mady Mellor66efd5e2019-05-15 13:38:11 -07005621 // Reset as this is called when the notif is first sent
5622 reset(mListeners);
5623
Mady Mellora54e9fa2019-04-18 13:26:18 -07005624 // Would be a normal notification because wouldn't have met requirements to bubble
5625 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5626 assertEquals(1, notifsBefore.length);
5627 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5628
5629 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005630 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005631 waitForIdle();
5632
5633 // We still wouldn't be a bubble because the notification didn't meet requirements
5634 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5635 assertEquals(1, notifsAfter.length);
5636 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5637 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005638
5639 @Test
Mady Mellor13f9bc82020-03-24 19:09:28 -07005640 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005641 setUpPrefsForBubbles(PKG, mUid,
5642 true /* global */,
5643 BUBBLE_PREFERENCE_ALL /* app */,
5644 true /* channel */);
5645
Mady Mellor13f9bc82020-03-24 19:09:28 -07005646 // Notif with bubble metadata
5647 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5648 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
5649
5650 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5651 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5652 waitForIdle();
5653 // Flag shouldn't be modified
5654 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5655 assertFalse(recordToCheck.isFlagBubbleRemoved());
5656
5657 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005658 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005659 waitForIdle();
5660 // Flag should be modified
5661 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5662 assertTrue(recordToCheck.isFlagBubbleRemoved());
5663
5664
5665 // Update the notif
5666 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5667 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5668 waitForIdle();
5669 // And the flag is reset
5670 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5671 assertFalse(recordToCheck.isFlagBubbleRemoved());
5672 }
5673
5674 @Test
5675 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005676 setUpPrefsForBubbles(PKG, mUid,
5677 true /* global */,
5678 BUBBLE_PREFERENCE_ALL /* app */,
5679 true /* channel */);
5680
Mady Mellor13f9bc82020-03-24 19:09:28 -07005681 // Notif with bubble metadata
5682 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5683 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
5684
5685 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5686 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5687 waitForIdle();
5688 // Flag shouldn't be modified
5689 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5690 assertFalse(recordToCheck.isFlagBubbleRemoved());
5691
5692 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005693 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005694 waitForIdle();
5695 // Flag should be modified
5696 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5697 assertTrue(recordToCheck.isFlagBubbleRemoved());
5698
5699 // Notify we are a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005700 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005701 waitForIdle();
5702 // And the flag is reset
5703 assertFalse(recordToCheck.isFlagBubbleRemoved());
5704 }
5705
5706 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -08005707 public void testOnBubbleNotificationSuppressionChanged() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005708 setUpPrefsForBubbles(PKG, mUid,
5709 true /* global */,
5710 BUBBLE_PREFERENCE_ALL /* app */,
5711 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08005712
Mady Mellorf44b6832020-01-14 13:26:14 -08005713 // Bubble notification
5714 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5715
Julia Reynolds24edc002020-01-29 16:35:32 -05005716 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5717 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorf44b6832020-01-14 13:26:14 -08005718 waitForIdle();
5719
5720 // NOT suppressed
5721 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5722 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5723
5724 // Reset as this is called when the notif is first sent
5725 reset(mListeners);
5726
5727 // Test: update suppression to true
5728 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
5729 waitForIdle();
5730
5731 // Check
5732 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5733 assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
5734
5735 // Reset to check again
5736 reset(mListeners);
5737
5738 // Test: update suppression to false
5739 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
5740 waitForIdle();
5741
5742 // Check
5743 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5744 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5745 }
5746
5747 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005748 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
5749 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5750 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005751 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005752 waitForIdle();
5753
5754 // A notification exists for the given record
5755 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5756 assertEquals(1, notifsBefore.length);
5757
5758 reset(mPackageManager);
5759
5760 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5761
5762 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005763 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5764 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005765
5766 // Grant permission called for the UID of SystemUI under the target user ID
5767 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005768 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5769 anyInt(), eq(nr.getSbn().getUserId()));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005770 }
5771
5772 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005773 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
5774 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5775 waitForIdle();
5776
5777 // No notifications exist for the given record
5778 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5779 assertEquals(0, notifsBefore.length);
5780
5781 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5782 int uid = 0; // sysui on primary user
5783
5784 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005785 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5786 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005787
5788 // Grant permission still called if no NotificationRecord exists for the given key
5789 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005790 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5791 anyInt(), eq(nr.getSbn().getUserId()));
Aran Ink979c9762019-10-24 16:09:45 -04005792 }
5793
5794 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005795 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
5796 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5797 NotificationRecord nr =
5798 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
5799 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005800 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005801 waitForIdle();
5802
5803 // A notification exists for the given record
5804 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5805 assertEquals(1, notifsBefore.length);
5806
5807 reset(mPackageManager);
5808
5809 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5810
5811 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005812 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5813 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005814
5815 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5816 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005817 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5818 anyInt(), eq(UserHandle.USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005819 }
5820
5821 @Test
5822 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
5823 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5824 int otherUserId = 11;
5825 NotificationRecord nr =
5826 generateNotificationRecord(mTestNotificationChannel, otherUserId);
5827 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005828 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005829 waitForIdle();
5830
5831 // A notification exists for the given record
5832 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5833 assertEquals(1, notifsBefore.length);
5834
5835 reset(mPackageManager);
5836
5837 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5838
5839 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04005840 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04005841 String sysuiPackage = "sysui";
5842 final String[] sysuiPackages = new String[] { sysuiPackage };
5843 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
5844
5845 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
5846 // time this is called
5847 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
5848 .thenReturn(otherUserUid);
5849
Aran Ink979c9762019-10-24 16:09:45 -04005850 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005851 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005852
5853 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5854 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005855 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
Aran Inkfd2bfd32019-10-04 16:30:01 -04005856 eq(otherUserId));
5857 }
5858
5859 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005860 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
5861 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5862 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005863
Aran Ink979c9762019-10-24 16:09:45 -04005864 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5865 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005866
Aran Ink979c9762019-10-24 16:09:45 -04005867 // create an inline record with two uris in it
5868 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005869 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5870 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005871 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005872 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5873 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005874
Aran Ink979c9762019-10-24 16:09:45 -04005875 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5876 assertNotNull(record); // record exists
5877 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04005878
Julia Reynolds24edc002020-01-29 16:35:32 -05005879 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
5880 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005881
5882 // permissionOwner destroyed
5883 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5884 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
5885 }
5886
5887
5888 @Test
5889 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
5890 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5891 reset(mPackageManager);
5892
Julia Reynolds24edc002020-01-29 16:35:32 -05005893 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
5894 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005895
5896 // no permissionOwner destroyed
5897 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
5898 any(), eq(null), eq(~0), eq(nr.getUserId()));
5899 }
5900
5901 @Test
5902 public void testClearInlineReplyUriPermission_userAll() throws Exception {
5903 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5904 UserHandle.USER_ALL);
5905 reset(mPackageManager);
5906
5907 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5908 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
5909
5910 // create an inline record a uri in it
5911 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005912 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5913 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005914
5915 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5916 assertNotNull(record); // record exists
5917
Julia Reynolds24edc002020-01-29 16:35:32 -05005918 mService.mNotificationDelegate.clearInlineReplyUriPermissions(
5919 nr.getKey(), nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005920
5921 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
5922 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5923 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005924 }
5925
5926 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005927 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005928 setUpPrefsForBubbles(PKG, mUid,
5929 true /* global */,
5930 BUBBLE_PREFERENCE_ALL /* app */,
5931 true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005932
Mady Mellor9e923e12019-12-17 16:08:46 -08005933 // And we are low ram
5934 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5935
5936 // Notification that would typically bubble
5937 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5938 "testNotificationBubbles_disabled_lowRamDevice");
Julia Reynolds24edc002020-01-29 16:35:32 -05005939 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5940 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005941 waitForIdle();
5942
Mady Mellor9e923e12019-12-17 16:08:46 -08005943 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005944 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5945 assertEquals(1, notifsAfter.length);
5946 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005947 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04005948
5949 @Test
5950 public void testRemoveLargeRemoteViews() throws Exception {
5951 int removeSize = mContext.getResources().getInteger(
5952 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
5953
5954 RemoteViews rv = mock(RemoteViews.class);
5955 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
5956 when(rv.clone()).thenReturn(rv);
5957 RemoteViews rv1 = mock(RemoteViews.class);
5958 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
5959 when(rv1.clone()).thenReturn(rv1);
5960 RemoteViews rv2 = mock(RemoteViews.class);
5961 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
5962 when(rv2.clone()).thenReturn(rv2);
5963 RemoteViews rv3 = mock(RemoteViews.class);
5964 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
5965 when(rv3.clone()).thenReturn(rv3);
5966 RemoteViews rv4 = mock(RemoteViews.class);
5967 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
5968 when(rv4.clone()).thenReturn(rv4);
5969 // note: different!
5970 RemoteViews rv5 = mock(RemoteViews.class);
5971 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
5972 when(rv5.clone()).thenReturn(rv5);
5973
5974 Notification np = new Notification.Builder(mContext, "test")
5975 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5976 .setContentText("test")
5977 .setCustomContentView(rv)
5978 .setCustomBigContentView(rv1)
5979 .setCustomHeadsUpContentView(rv2)
5980 .build();
5981 Notification n = new Notification.Builder(mContext, "test")
5982 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5983 .setContentText("test")
5984 .setCustomContentView(rv3)
5985 .setCustomBigContentView(rv4)
5986 .setCustomHeadsUpContentView(rv5)
5987 .setPublicVersion(np)
5988 .build();
5989
5990 assertNotNull(np.contentView);
5991 assertNotNull(np.bigContentView);
5992 assertNotNull(np.headsUpContentView);
5993
5994 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
5995 assertNotNull(n.publicVersion.contentView);
5996 assertNotNull(n.publicVersion.bigContentView);
5997 assertNotNull(n.publicVersion.headsUpContentView);
5998
5999 mService.fixNotification(n, PKG, "tag", 9, 0);
6000
6001 assertNull(n.contentView);
6002 assertNull(n.bigContentView);
6003 assertNotNull(n.headsUpContentView);
6004 assertNull(n.publicVersion.contentView);
6005 assertNull(n.publicVersion.bigContentView);
6006 assertNull(n.publicVersion.headsUpContentView);
6007
6008 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
6009 }
Mady Mellor06b770c2019-08-29 18:01:00 -07006010
Colin Cross5ea7fb72019-12-18 17:16:36 -08006011 @Test
Mady Mellora7731962019-06-17 17:57:02 -07006012 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
6013 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006014 setUpPrefsForBubbles(PKG, mUid,
6015 true /* global */,
6016 BUBBLE_PREFERENCE_ALL /* app */,
6017 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006018
Mady Mellor9e923e12019-12-17 16:08:46 -08006019 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6020 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
6021 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006022 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006023 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6024 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006025
6026 // Ensure we're not foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006027 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006028 IMPORTANCE_VISIBLE);
6029
Julia Reynolds24edc002020-01-29 16:35:32 -05006030 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6031 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006032 waitForIdle();
6033
6034 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006035 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006036 assertTrue(notif.isBubbleNotification());
6037
6038 // Our flags should have failed since we're not foreground
6039 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
6040 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
6041 }
6042
6043 @Test
6044 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
6045 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006046 setUpPrefsForBubbles(PKG, mUid,
6047 true /* global */,
6048 BUBBLE_PREFERENCE_ALL /* app */,
6049 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006050
Mady Mellor9e923e12019-12-17 16:08:46 -08006051 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6052 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
6053 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006054 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006055 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6056 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006057
6058 // Ensure we are in the foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006059 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006060 IMPORTANCE_FOREGROUND);
6061
Julia Reynolds24edc002020-01-29 16:35:32 -05006062 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6063 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006064 waitForIdle();
6065
6066 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006067 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006068 assertTrue(notif.isBubbleNotification());
6069
Mady Mellor9e923e12019-12-17 16:08:46 -08006070 // Our flags should have passed since we are foreground
Mady Mellora7731962019-06-17 17:57:02 -07006071 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
6072 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
6073 }
Mady Mellor22f2f072019-04-18 13:26:18 -07006074
6075 @Test
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006076 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
6077 throws RemoteException {
Danning Chen28410f32020-04-21 10:28:52 -07006078 final String shortcutId = "someshortcutId";
Mady Mellora92268c2020-03-09 17:25:08 -07006079 setUpPrefsForBubbles(PKG, mUid,
6080 true /* global */,
6081 BUBBLE_PREFERENCE_ALL /* app */,
6082 true /* channel */);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006083
6084 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6085 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6086
6087 // Messaging notification with shortcut info
6088 Notification.BubbleMetadata metadata =
Danning Chen28410f32020-04-21 10:28:52 -07006089 new Notification.BubbleMetadata.Builder(shortcutId).build();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006090 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6091 null /* groupKey */, false /* isSummary */);
Danning Chen28410f32020-04-21 10:28:52 -07006092 nb.setShortcutId(shortcutId);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006093 nb.setBubbleMetadata(metadata);
6094 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6095 "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
6096 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6097
6098 // Pretend the shortcut exists
6099 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
Julia Reynoldsd61bdf12020-02-25 12:25:07 -05006100 ShortcutInfo info = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006101 when(info.getPackage()).thenReturn(PKG);
Danning Chen28410f32020-04-21 10:28:52 -07006102 when(info.getId()).thenReturn(shortcutId);
Danning Chen07cfaa62020-04-20 15:16:41 -07006103 when(info.getUserId()).thenReturn(USER_SYSTEM);
Julia Reynoldsd61bdf12020-02-25 12:25:07 -05006104 when(info.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006105 when(info.isEnabled()).thenReturn(true);
Julia Reynoldsd61bdf12020-02-25 12:25:07 -05006106 shortcutInfos.add(info);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006107 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006108 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6109 anyString(), anyInt(), any())).thenReturn(true);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006110
6111 // Test: Send the bubble notification
Julia Reynolds24edc002020-01-29 16:35:32 -05006112 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6113 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006114 waitForIdle();
6115
6116 // Verify:
6117
6118 // Make sure we register the callback for shortcut changes
6119 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6120
6121 // yes allowed, yes messaging w/shortcut, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006122 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006123 assertTrue(notif.isBubbleNotification());
6124
Danning Chen28410f32020-04-21 10:28:52 -07006125 // Make sure the shortcut is cached.
6126 verify(mShortcutServiceInternal).cacheShortcuts(
6127 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
6128 eq(USER_SYSTEM));
6129
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006130 // Test: Remove the shortcut
Mady Mellor56515c42020-02-18 17:58:36 -08006131 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006132 launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
6133 new UserHandle(mUid));
Mady Mellor56515c42020-02-18 17:58:36 -08006134 waitForIdle();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006135
6136 // Verify:
6137
6138 // Make sure callback is unregistered
6139 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6140
6141 // We're no longer a bubble
Julia Reynoldsd61bdf12020-02-25 12:25:07 -05006142 Notification notif2 = mService.getNotificationRecord(
6143 nr.getSbn().getKey()).getNotification();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006144 assertFalse(notif2.isBubbleNotification());
6145 }
6146
Mady Mellor56515c42020-02-18 17:58:36 -08006147
6148 @Test
6149 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
6150 throws RemoteException {
Danning Chen28410f32020-04-21 10:28:52 -07006151 final String shortcutId = "someshortcutId";
Mady Mellora92268c2020-03-09 17:25:08 -07006152 setUpPrefsForBubbles(PKG, mUid,
6153 true /* global */,
6154 BUBBLE_PREFERENCE_ALL /* app */,
6155 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08006156
6157 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6158 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6159
6160 // Messaging notification with shortcut info
Mady Melloraa9ce172020-03-17 10:34:20 -07006161 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
Danning Chen28410f32020-04-21 10:28:52 -07006162 shortcutId).build();
Mady Mellor56515c42020-02-18 17:58:36 -08006163 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6164 null /* groupKey */, false /* isSummary */);
Danning Chen28410f32020-04-21 10:28:52 -07006165 nb.setShortcutId(shortcutId);
Mady Mellor56515c42020-02-18 17:58:36 -08006166 nb.setBubbleMetadata(metadata);
6167 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6168 "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
6169 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6170
6171 // Pretend the shortcut exists
6172 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
6173 ShortcutInfo info = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006174 when(info.getPackage()).thenReturn(PKG);
Danning Chen28410f32020-04-21 10:28:52 -07006175 when(info.getId()).thenReturn(shortcutId);
Danning Chen07cfaa62020-04-20 15:16:41 -07006176 when(info.getUserId()).thenReturn(USER_SYSTEM);
Mady Mellor56515c42020-02-18 17:58:36 -08006177 when(info.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006178 when(info.isEnabled()).thenReturn(true);
Mady Mellor56515c42020-02-18 17:58:36 -08006179 shortcutInfos.add(info);
6180 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006181 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6182 anyString(), anyInt(), any())).thenReturn(true);
Mady Mellor56515c42020-02-18 17:58:36 -08006183
6184 // Test: Send the bubble notification
6185 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6186 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6187 waitForIdle();
6188
6189 // Verify:
6190
6191 // Make sure we register the callback for shortcut changes
6192 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6193
6194 // yes allowed, yes messaging w/shortcut, yes bubble
6195 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6196 assertTrue(notif.isBubbleNotification());
6197
Danning Chen28410f32020-04-21 10:28:52 -07006198 // Make sure the shortcut is cached.
6199 verify(mShortcutServiceInternal).cacheShortcuts(
6200 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
6201 eq(USER_SYSTEM));
6202
Mady Mellor56515c42020-02-18 17:58:36 -08006203 // Test: Remove the notification
6204 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6205 nr.getSbn().getId(), nr.getSbn().getUserId());
6206 waitForIdle();
6207
6208 // Verify:
6209
6210 // Make sure callback is unregistered
6211 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6212 }
6213
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006214 @Test
Mady Mellor22f2f072019-04-18 13:26:18 -07006215 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
6216 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006217 setUpPrefsForBubbles(PKG, mUid,
6218 true /* global */,
6219 BUBBLE_PREFERENCE_ALL /* app */,
6220 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006221
6222 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6223 true /* summaryAutoCancel */);
6224
6225 // Dismiss summary
6226 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6227 true);
Julia Reynolds24edc002020-01-29 16:35:32 -05006228 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
6229 nrSummary.getSbn().getTag(),
6230 nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
Mady Mellor22f2f072019-04-18 13:26:18 -07006231 NotificationStats.DISMISSAL_SHADE,
6232 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
6233 waitForIdle();
6234
6235 // The bubble should still exist
6236 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6237 assertEquals(1, notifsAfter.length);
6238 }
6239
6240 @Test
6241 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
6242 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006243 setUpPrefsForBubbles(PKG, mUid,
6244 true /* global */,
6245 BUBBLE_PREFERENCE_ALL /* app */,
6246 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006247
6248 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6249 true /* summaryAutoCancel */);
6250
6251 // Click summary
6252 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6253 true);
6254 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6255 nrSummary.getKey(), nv);
6256 waitForIdle();
6257
6258 // 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 and associated dismissal logs
6263 assertEquals(6, mNotificationRecordLogger.numCalls());
6264 // Skip the notification-creation logs
6265 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6266 mNotificationRecordLogger.event(3));
6267 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
6268 mNotificationRecordLogger.event(4));
6269 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
6270 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
6271 mNotificationRecordLogger.event(5));
Mady Mellor22f2f072019-04-18 13:26:18 -07006272 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04006273
6274 @Test
Beverly9e6a7642020-02-13 10:11:29 -05006275 public void testNotificationBubbles_bubbleStays_whenClicked()
6276 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006277 setUpPrefsForBubbles(PKG, mUid,
6278 true /* global */,
6279 BUBBLE_PREFERENCE_ALL /* app */,
6280 true /* channel */);
6281
Beverly9e6a7642020-02-13 10:11:29 -05006282 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
Beverly9e6a7642020-02-13 10:11:29 -05006283 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
6284 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
6285 mService.addNotification(nr);
6286
6287 // WHEN we click the notification
6288 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
6289 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6290 nr.getKey(), nv);
6291 waitForIdle();
6292
6293 // THEN the bubble should still exist
6294 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6295 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006296
6297 // Check we got the click log
6298 assertEquals(1, mNotificationRecordLogger.numCalls());
6299 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6300 mNotificationRecordLogger.event(0));
Beverly9e6a7642020-02-13 10:11:29 -05006301 }
6302
6303 @Test
Julia Reynolds57a974b2019-10-07 11:51:47 -04006304 public void testLoadDefaultApprovedServices_emptyResources() {
6305 TestableResources tr = mContext.getOrCreateTestableResources();
6306 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
6307 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
6308 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
6309 setDefaultAssistantInDeviceConfig("");
6310
6311 mService.loadDefaultApprovedServices(USER_SYSTEM);
6312
6313 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
6314 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
6315 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
6316 }
6317
6318 @Test
6319 public void testLoadDefaultApprovedServices_dnd() {
6320 TestableResources tr = mContext.getOrCreateTestableResources();
6321 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
6322 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
6323 .thenReturn(new ArraySet<>());
6324
6325 mService.loadDefaultApprovedServices(USER_SYSTEM);
6326
Jay Aliomer76e1f2722020-03-05 12:36:38 -05006327 verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
Julia Reynolds57a974b2019-10-07 11:51:47 -04006328 }
6329
6330 // TODO: add tests for the rest of the non-empty cases
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006331
6332 @Test
6333 public void testOnUnlockUser() {
6334 UserInfo ui = new UserInfo();
6335 ui.id = 10;
6336 mService.onUnlockUser(ui);
6337 waitForIdle();
6338
6339 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
6340 }
6341
6342 @Test
6343 public void testOnStopUser() {
6344 UserInfo ui = new UserInfo();
6345 ui.id = 10;
6346 mService.onStopUser(ui);
6347 waitForIdle();
6348
6349 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
6350 }
6351
6352 @Test
6353 public void testOnBootPhase() {
6354 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
6355
6356 verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
6357
6358 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
6359
6360 verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart();
6361 }
6362
6363 @Test
6364 public void testHandleOnPackageChanged() {
6365 String[] pkgs = new String[] {PKG, PKG_N_MR1};
6366 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
6367
6368 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
6369
6370 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
6371
6372 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
6373
6374 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
6375 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
6376 }
6377
6378 @Test
6379 public void testNotificationHistory_addNoisyNotification() throws Exception {
6380 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08006381 null /* tvExtender */);
Julia Reynolds24edc002020-01-29 16:35:32 -05006382 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6383 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006384 waitForIdle();
6385
6386 verify(mHistoryManager, times(1)).addNotification(any());
6387 }
Julia Reynolds0f767342019-12-18 09:11:55 -05006388
6389 @Test
6390 public void createConversationNotificationChannel() throws Exception {
6391 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
6392 original.setAllowBubbles(!original.canBubble());
6393 original.setShowBadge(!original.canShowBadge());
6394
6395 Parcel parcel = Parcel.obtain();
6396 original.writeToParcel(parcel, 0);
6397 parcel.setDataPosition(0);
6398 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
6399 assertEquals(original, orig);
6400 assertFalse(TextUtils.isEmpty(orig.getName()));
6401
6402 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6403 orig)));
6404
Julia Reynolds7c267522020-01-16 11:26:41 -05006405 mBinderService.createConversationNotificationChannelForPackage(
6406 PKG, mUid, "key", orig, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006407
6408 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006409 PKG, 0, PKG, original.getId(), false, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006410
6411 assertEquals(original.getName(), friendChannel.getName());
6412 assertEquals(original.getId(), friendChannel.getParentChannelId());
6413 assertEquals("friend", friendChannel.getConversationId());
6414 assertEquals(null, original.getConversationId());
6415 assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
Mady Mellora92268c2020-03-09 17:25:08 -07006416 assertFalse(friendChannel.canBubble()); // can't be modified by app
Julia Reynolds0f767342019-12-18 09:11:55 -05006417 assertFalse(original.getId().equals(friendChannel.getId()));
6418 assertNotNull(friendChannel.getId());
6419 }
6420
6421 @Test
6422 public void deleteConversationNotificationChannels() throws Exception {
6423 NotificationChannel messagesParent =
6424 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
6425 Parcel msgParcel = Parcel.obtain();
6426 messagesParent.writeToParcel(msgParcel, 0);
6427 msgParcel.setDataPosition(0);
6428
6429 NotificationChannel callsParent =
6430 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
6431 Parcel callParcel = Parcel.obtain();
6432 callsParent.writeToParcel(callParcel, 0);
6433 callParcel.setDataPosition(0);
6434
6435 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6436 messagesParent, callsParent)));
6437
6438 String conversationId = "friend";
6439
6440 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006441 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
6442 conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006443 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006444 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
Julia Reynolds0f767342019-12-18 09:11:55 -05006445 conversationId);
6446
6447 NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006448 PKG, 0, PKG, messagesParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006449 NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006450 PKG, 0, PKG, callsParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006451
6452 assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
6453 assertEquals(conversationId, messagesChild.getConversationId());
6454
6455 assertEquals(callsParent.getId(), callsChild.getParentChannelId());
6456 assertEquals(conversationId, callsChild.getConversationId());
6457
6458 mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
6459
6460 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006461 PKG, 0, PKG, messagesParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006462 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006463 PKG, 0, PKG, callsParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006464 }
Julia Reynolds24edc002020-01-29 16:35:32 -05006465
6466 @Test
6467 public void testCorrectCategory_systemOn_appCannotTurnOff() {
6468 int requested = 0;
6469 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6470
6471 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6472 system);
6473
6474 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
6475 }
6476
6477 @Test
6478 public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
6479 int requested = PRIORITY_CATEGORY_CALLS;
6480 int system = PRIORITY_CATEGORY_CALLS;
6481
6482 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6483 system);
6484
6485 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6486 }
6487
6488 @Test
6489 public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
6490 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6491 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6492
6493 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6494 system);
6495
6496 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
6497 }
6498
6499 @Test
6500 public void testCorrectCategory_systemOff_appCannotTurnOn() {
6501 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6502 int system = PRIORITY_CATEGORY_CALLS;
6503
6504 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6505 system);
6506
6507 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6508 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006509
6510 @Test
6511 public void testGetConversationsForPackage_hasShortcut() throws Exception {
6512 mService.setPreferencesHelper(mPreferencesHelper);
6513 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6514 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6515 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6516 channel1.setConversationId("parent1", "convo 1");
6517 convo1.setNotificationChannel(channel1);
6518 convos.add(convo1);
6519
6520 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6521 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6522 channel2.setConversationId("parent1", "convo 2");
6523 convo2.setNotificationChannel(channel2);
6524 convos.add(convo2);
6525 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6526
Julia Reynolds882f2062020-02-05 12:11:38 -05006527 ShortcutInfo si = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006528 when(si.getPackage()).thenReturn(PKG_P);
6529 when(si.getId()).thenReturn("convo");
6530 when(si.getUserId()).thenReturn(USER_SYSTEM);
Julia Reynolds882f2062020-02-05 12:11:38 -05006531 when(si.getShortLabel()).thenReturn("Hello");
Mady Mellor774d5fe2020-03-05 11:35:03 -08006532 when(si.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006533 when(si.isEnabled()).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006534 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
Julia Reynoldsfa273072020-04-14 15:31:21 -04006535 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6536 anyString(), anyInt(), any())).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006537
6538 List<ConversationChannelWrapper> conversations =
6539 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6540 assertEquals(si, conversations.get(0).getShortcutInfo());
6541 assertEquals(si, conversations.get(1).getShortcutInfo());
Mady Mellor774d5fe2020-03-05 11:35:03 -08006542 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006543
Mady Mellor774d5fe2020-03-05 11:35:03 -08006544 @Test
6545 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
6546 mService.setPreferencesHelper(mPreferencesHelper);
6547 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6548 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6549 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6550 channel1.setConversationId("parent1", "convo 1");
6551 convo1.setNotificationChannel(channel1);
6552 convos.add(convo1);
6553
6554 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6555 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6556 channel2.setConversationId("parent1", "convo 2");
6557 convo2.setNotificationChannel(channel2);
6558 convos.add(convo2);
6559 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6560
6561 ShortcutInfo si = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006562 when(si.getPackage()).thenReturn(PKG_P);
6563 when(si.getId()).thenReturn("convo");
6564 when(si.getUserId()).thenReturn(USER_SYSTEM);
Mady Mellor774d5fe2020-03-05 11:35:03 -08006565 when(si.getShortLabel()).thenReturn("Hello");
6566 when(si.isLongLived()).thenReturn(false);
6567 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6568
6569 List<ConversationChannelWrapper> conversations =
6570 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6571 assertNull(conversations.get(0).getShortcutInfo());
6572 assertNull(conversations.get(1).getShortcutInfo());
Julia Reynolds882f2062020-02-05 12:11:38 -05006573 }
6574
6575 @Test
6576 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
6577 mService.setPreferencesHelper(mPreferencesHelper);
6578 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6579 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6580 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6581 channel1.setConversationId("parent1", "convo 1");
6582 convo1.setNotificationChannel(channel1);
6583 convos.add(convo1);
6584
6585 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6586 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6587 channel2.setConversationId("parent1", "convo 2");
6588 convo2.setNotificationChannel(channel2);
6589 convos.add(convo2);
6590 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6591
6592 List<ConversationChannelWrapper> conversations =
6593 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6594 assertNull(conversations.get(0).getShortcutInfo());
6595 assertNull(conversations.get(1).getShortcutInfo());
6596 }
Mady Mellor57b34162020-04-01 08:44:00 -07006597
6598 @Test
6599 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
6600 mService.setShortcutHelper(null);
6601 NotificationRecord nr =
6602 generateMessageBubbleNotifRecord(mTestNotificationChannel,
6603 "testShortcutHelperNull_doesntCrashEnqueue");
6604 try {
6605 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6606 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6607 waitForIdle();
6608 } catch (Exception e) {
6609 fail(e.getMessage());
6610 }
6611 }
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006612
6613 @Test
6614 public void testRecordMessages() throws RemoteException {
6615 NotificationRecord nr =
6616 generateMessageBubbleNotifRecord(mTestNotificationChannel,
6617 "testRecordMessages");
6618 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6619 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6620 waitForIdle();
6621
6622 assertTrue(mBinderService.hasSentMessage(PKG, mUid));
6623 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05006624}