blob: 16aa87b3e59cff7e0f1c1ac98204c588eda0ba40 [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;
Chris Wren0f0e8772020-06-10 10:02:19 -0400181import org.junit.Ignore;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400182import org.junit.Test;
183import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500184import org.mockito.ArgumentCaptor;
185import org.mockito.Mock;
186import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400187import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400188import org.xmlpull.v1.XmlPullParser;
189import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500190
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400191import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400192import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400193import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400194import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400195import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400196import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400197import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500198import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000199import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400200import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400201import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200202import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500203
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400204
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400205@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400206@RunWith(AndroidTestingRunner.class)
207@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500208public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500209 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000210
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400211 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500212 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500213 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400214 private NotificationManagerInternal mInternalService;
Mady Mellor56515c42020-02-18 17:58:36 -0800215 private ShortcutHelper mShortcutHelper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400216 @Mock
217 private IPackageManager mPackageManager;
218 @Mock
219 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400220 @Mock
221 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400222 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500223 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400224 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400225 @Mock
226 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400227 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400228 AtomicFile mPolicyFile;
229 File mFile;
230 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400231 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400232 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400233 private UsageStatsManagerInternal mAppUsageStats;
234 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400235 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400236 @Mock
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800237 private LauncherApps mLauncherApps;
238 @Mock
Julia Reynoldsfa273072020-04-14 15:31:21 -0400239 private ShortcutServiceInternal mShortcutServiceInternal;
240 @Mock
Julia Reynolds68263d12017-06-21 14:21:19 -0400241 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200242 @Mock
243 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400244 @Mock
245 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400246
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500247 private static final int MAX_POST_DELAY = 1000;
248
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500249 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500250 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000251
252 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
253
Julia Reynoldsc76888d2020-05-04 15:36:09 -0400254 private static final String VALID_CONVO_SHORTCUT_ID = "shortcut";
255
Julia Reynoldsda781472017-04-12 09:41:16 -0400256 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400257 private NotificationListeners mListeners;
258 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400259 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400260 private ManagedServices.ManagedServiceInfo mListener;
261 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400262 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400263 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400264 @Mock
265 IBinder mPermOwner;
266 @Mock
267 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700268 @Mock
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000269 ActivityTaskManagerInternal mAtm;
270 @Mock
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700271 IUriGrantsManager mUgm;
272 @Mock
273 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400274 @Mock
275 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000276 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000277 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
278 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400279 @Mock
280 UserManager mUm;
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500281 @Mock
282 NotificationHistoryManager mHistoryManager;
Yotam Aron74299972020-01-16 16:20:58 +0200283 @Mock
284 StatsManager mStatsManager;
Will Brockman2b6959e2020-01-22 09:59:50 -0500285 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
Will Brockmancfd98302020-01-29 15:57:30 -0500286 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
287 1 << 30);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000288 @Mock
289 StatusBarManagerInternal mStatusBar;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500290
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400291 // Use a Testable subclass so we can simulate calls from the system without failing.
292 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500293 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700294 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000295 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000296 @Nullable
297 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500298
Will Brockmancfd98302020-01-29 15:57:30 -0500299 TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
300 InstanceIdSequence notificationInstanceIdSequence) {
301 super(context, logger, notificationInstanceIdSequence);
Amith Yamasani803eab692017-11-09 17:47:04 -0800302 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400303
Mady Mellor56515c42020-02-18 17:58:36 -0800304 RankingHelper getRankingHelper() {
305 return mRankingHelper;
306 }
307
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400308 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400309 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500310 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700311 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400312 }
313
314 @Override
315 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500316 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700317 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400318 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400319
320 @Override
321 protected ICompanionDeviceManager getCompanionManager() {
322 return null;
323 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800324
325 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800326 protected void reportUserInteraction(NotificationRecord r) {
327 return;
328 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500329
330 @Override
331 protected void handleSavePolicyFile() {
332 return;
333 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000334
335 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000336 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
337 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000338 countLogSmartSuggestionsVisible++;
339 }
340
Annie Meng8b646fd2019-02-01 18:46:42 +0000341 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000342 protected void setNotificationAssistantAccessGrantedForUserInternal(
343 ComponentName assistant, int userId, boolean granted) {
344 if (mNotificationAssistantAccessGrantedCallback != null) {
345 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
346 return;
347 }
348 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
349 }
350
Julia Reynoldse61758a2020-06-10 10:26:44 -0400351 @Override
352 protected String[] getStringArrayResource(int key) {
353 return new String[] {PKG_O};
354 }
355
Tony Mak9a3c1f12019-03-04 16:04:42 +0000356 private void setNotificationAssistantAccessGrantedCallback(
357 @Nullable NotificationAssistantAccessGrantedCallback callback) {
358 this.mNotificationAssistantAccessGrantedCallback = callback;
359 }
360
361 interface NotificationAssistantAccessGrantedCallback {
362 void onGranted(ComponentName assistant, int userId, boolean granted);
363 }
Mady Mellor56515c42020-02-18 17:58:36 -0800364 }
365
Beverly58b24532018-10-02 09:08:23 -0400366 private class TestableToastCallback extends ITransientNotification.Stub {
367 @Override
368 public void show(IBinder windowToken) {
369 }
370
371 @Override
372 public void hide() {
373 }
374 }
375
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500376 @Before
377 public void setUp() throws Exception {
Beverly24d103b2020-02-18 17:40:57 -0500378 // Shell permisssions will override permissions of our app, so add all necessary permissions
Beverly080782f2020-02-24 16:42:57 -0500379 // for this test here:
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000380 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Beverly24d103b2020-02-18 17:40:57 -0500381 "android.permission.WRITE_DEVICE_CONFIG",
382 "android.permission.READ_DEVICE_CONFIG",
383 "android.permission.READ_CONTACTS");
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000384
Julia Reynoldsda781472017-04-12 09:41:16 -0400385 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400386
Mady Mellor13f9bc82020-03-24 19:09:28 -0700387 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
388 when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
389 ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
390
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700391 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
392 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400393 LocalServices.removeServiceForTest(WindowManagerInternal.class);
394 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000395 LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
396 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
Mady Mellor13f9bc82020-03-24 19:09:28 -0700397 LocalServices.removeServiceForTest(DeviceIdleInternal.class);
398 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
399 LocalServices.removeServiceForTest(ActivityManagerInternal.class);
400 LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700401
Julia Reynolds4afe2642019-05-01 08:42:24 -0400402 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
403
Will Brockmancfd98302020-01-29 15:57:30 -0500404 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
405 mNotificationInstanceIdSequence);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500406
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400407 // Use this testable looper.
408 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500409 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400410 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400411
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400412 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400413 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
414 Object[] args = invocation.getArguments();
415 return getApplicationInfo((String) args[0], mUid);
416 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500417 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400418 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
419 Object[] args = invocation.getArguments();
420 return getApplicationInfo((String) args[0], mUid);
421 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400422 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500423 final LightsManager mockLightsManager = mock(LightsManager.class);
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100424 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400425 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400426 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700427 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400428 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400429 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400430 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500431
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400432 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400433 mFile = new File(mContext.getCacheDir(), "test.xml");
434 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400435 final String preupgradeXml = "<notification-policy></notification-policy>";
436 mPolicyFile = new AtomicFile(mFile);
437 FileOutputStream fos = mPolicyFile.startWrite();
438 fos.write(preupgradeXml.getBytes());
439 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400440
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400441 // Setup managed services
442 mListener = mListeners.new ManagedServiceInfo(
Julia Reynoldse61758a2020-06-10 10:26:44 -0400443 null, new ComponentName(PKG, "test_class"),
444 UserHandle.getUserId(mUid), true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400445 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
446 ArraySet<ComponentName> components = new ArraySet<>();
447 components.add(defaultComponent);
448 when(mListeners.getDefaultComponents()).thenReturn(components);
449 when(mConditionProviders.getDefaultPackages())
450 .thenReturn(new ArraySet<>(Arrays.asList("config")));
451 when(mAssistants.getDefaultComponents()).thenReturn(components);
452 when(mAssistants.queryPackageForServices(
453 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldse61758a2020-06-10 10:26:44 -0400454 when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400455 ManagedServices.Config listenerConfig = new ManagedServices.Config();
456 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
457 when(mListeners.getConfig()).thenReturn(listenerConfig);
458 ManagedServices.Config assistantConfig = new ManagedServices.Config();
459 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
460 when(mAssistants.getConfig()).thenReturn(assistantConfig);
461 ManagedServices.Config dndConfig = new ManagedServices.Config();
462 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
463 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
464
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400465 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
466
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500467 mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
468 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400469 mListeners, mAssistants, mConditionProviders,
470 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000471 mGroupHelper, mAm, mAtm, mAppUsageStats,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400472 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400473 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
474 mock(TelephonyManager.class));
Julia Reynolds4afe2642019-05-01 08:42:24 -0400475 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
476
Julia Reynolds503ed942017-10-04 16:04:56 -0400477 mService.setAudioManager(mAudioManager);
Mady Mellor56515c42020-02-18 17:58:36 -0800478
479 mShortcutHelper = mService.getShortcutHelper();
480 mShortcutHelper.setLauncherApps(mLauncherApps);
Julia Reynoldsfa273072020-04-14 15:31:21 -0400481 mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
Mady Mellor56515c42020-02-18 17:58:36 -0800482
Julia Reynoldsc76888d2020-05-04 15:36:09 -0400483 // Pretend the shortcut exists
484 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
485 ShortcutInfo info = mock(ShortcutInfo.class);
486 when(info.getPackage()).thenReturn(PKG);
487 when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID);
488 when(info.getUserId()).thenReturn(USER_SYSTEM);
489 when(info.isLongLived()).thenReturn(true);
490 when(info.isEnabled()).thenReturn(true);
491 shortcutInfos.add(info);
492 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
493 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
494 anyString(), anyInt(), any())).thenReturn(true);
495
Mady Mellor56515c42020-02-18 17:58:36 -0800496 // Set the testable bubble extractor
497 RankingHelper rankingHelper = mService.getRankingHelper();
498 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
Mady Mellora92268c2020-03-09 17:25:08 -0700499 extractor.setActivityManager(mActivityManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500500
501 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400502 mBinderService = mService.getBinderService();
503 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500504
505 mBinderService.createNotificationChannels(
506 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldse61758a2020-06-10 10:26:44 -0400507 mBinderService.createNotificationChannels(
508 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
509 mBinderService.createNotificationChannels(
510 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400511 assertNotNull(mBinderService.getNotificationChannel(
512 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400513 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500514 }
515
Julia Reynoldsb852e562017-06-06 16:14:18 -0400516 @After
Will Brockman9918db92020-03-06 16:48:39 -0500517 public void assertNotificationRecordLoggerCallsValid() {
518 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
519 if (call.wasLogged) {
520 assertNotNull(call.event);
521 }
522 }
523 }
524
525 @After
Julia Reynoldsb852e562017-06-06 16:14:18 -0400526 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400527 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000528 clearDeviceConfig();
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500529 mService.unregisterDeviceConfigChange();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000530 InstrumentationRegistry.getInstrumentation()
531 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400532 }
533
Jay Aliomer4204f252019-08-26 11:36:53 -0400534 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
535 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
536 changed.put(true, new ArrayList<>());
537 changed.put(false, new ArrayList<>());
538 return changed;
539 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400540 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
541 final ApplicationInfo applicationInfo = new ApplicationInfo();
542 applicationInfo.uid = uid;
543 switch (pkg) {
544 case PKG_N_MR1:
545 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
546 break;
547 case PKG_O:
548 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
549 break;
550 case PKG_P:
551 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
552 break;
553 default:
554 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
555 break;
556 }
557 return applicationInfo;
558 }
559
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500560 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400561 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500562 }
563
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500564 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
Mady Mellora92268c2020-03-09 17:25:08 -0700565 int pkgPref, boolean channelEnabled) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500566 Settings.Global.putInt(mContext.getContentResolver(),
567 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
568 mService.mPreferencesHelper.updateBubblesEnabled();
569 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled());
570 try {
Mady Mellora92268c2020-03-09 17:25:08 -0700571 mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500572 } catch (RemoteException e) {
573 e.printStackTrace();
574 }
Mady Mellorc6820342019-05-20 12:04:36 -0700575 mTestNotificationChannel.setAllowBubbles(channelEnabled);
576 }
577
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500578 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
579 Notification.Builder nb = new Notification.Builder(mContext, "a")
580 .setContentTitle("foo")
581 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400582 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
583 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500584 nb.build(), new UserHandle(userId), null, postTime);
585 return sbn;
586 }
587
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400588 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
589 String groupKey, boolean isSummary) {
590 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
591 .setContentTitle("foo")
592 .setSmallIcon(android.R.drawable.sym_def_app_icon)
593 .setGroup(groupKey)
594 .setGroupSummary(isSummary);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400595 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
596 "tag" + System.currentTimeMillis(), mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -0400597 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000598 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400599 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400600
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500601 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500602 return generateNotificationRecord(channel, null);
603 }
604
605 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
606 Notification.TvExtender extender) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500607 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500608 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500609 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500610 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500611 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500612 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500613 if (extender != null) {
614 nb.extend(extender);
615 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400616 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -0400617 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000618 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500619 }
620
Aran Inkfd2bfd32019-10-04 16:30:01 -0400621 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
622 if (channel == null) {
623 channel = mTestNotificationChannel;
624 }
625 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
626 .setContentTitle("foo")
627 .setSmallIcon(android.R.drawable.sym_def_app_icon);
628 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
629 nb.build(), new UserHandle(userId), null, 0);
630 return new NotificationRecord(mContext, sbn, channel);
631 }
632
Mady Mellor9e923e12019-12-17 16:08:46 -0800633 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
634 String tag) {
635 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
636 }
637
638 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
639 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
640 if (channel == null) {
641 channel = mTestNotificationChannel;
642 }
643 if (tag == null) {
644 tag = "tag";
645 }
646 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
647 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
648 tag, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -0400649 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor9e923e12019-12-17 16:08:46 -0800650 return new NotificationRecord(mContext, sbn, channel);
651 }
652
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400653 private Map<String, Answer> getSignalExtractorSideEffects() {
654 Map<String, Answer> answers = new ArrayMap<>();
655
656 answers.put("override group key", invocationOnMock -> {
657 ((NotificationRecord) invocationOnMock.getArguments()[0])
658 .setOverrideGroupKey("bananas");
659 return null;
660 });
661 answers.put("override people", invocationOnMock -> {
662 ((NotificationRecord) invocationOnMock.getArguments()[0])
663 .setPeopleOverride(new ArrayList<>());
664 return null;
665 });
666 answers.put("snooze criteria", invocationOnMock -> {
667 ((NotificationRecord) invocationOnMock.getArguments()[0])
668 .setSnoozeCriteria(new ArrayList<>());
669 return null;
670 });
671 answers.put("notification channel", invocationOnMock -> {
672 ((NotificationRecord) invocationOnMock.getArguments()[0])
673 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
674 return null;
675 });
676 answers.put("badging", invocationOnMock -> {
677 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
678 r.setShowBadge(!r.canShowBadge());
679 return null;
680 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500681 answers.put("bubbles", invocationOnMock -> {
682 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
683 r.setAllowBubble(!r.canBubble());
684 return null;
685 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400686 answers.put("package visibility", invocationOnMock -> {
687 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
688 Notification.VISIBILITY_SECRET);
689 return null;
690 });
691
692 return answers;
693 }
694
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400695 private void clearDeviceConfig() {
696 DeviceConfig.resetToDefaults(
697 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
698 }
699
700 private void setDefaultAssistantInDeviceConfig(String componentName) {
701 DeviceConfig.setProperty(
702 DeviceConfig.NAMESPACE_SYSTEMUI,
703 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
704 componentName,
705 false);
706 }
707
Mady Mellor9e923e12019-12-17 16:08:46 -0800708 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
709 String groupKey, boolean isSummary) {
710 // Give it a person
711 Person person = new Person.Builder()
712 .setName("bubblebot")
713 .build();
Mady Mellor9e923e12019-12-17 16:08:46 -0800714 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
715 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
716 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
717 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
718 inputIntent).addRemoteInput(remoteInput)
719 .build();
720 // Make it messaging style
721 Notification.Builder nb = new Notification.Builder(mContext,
722 mTestNotificationChannel.getId())
723 .setContentTitle("foo")
724 .setStyle(new Notification.MessagingStyle(person)
725 .setConversationTitle("Bubble Chat")
726 .addMessage("Hello?",
727 SystemClock.currentThreadTimeMillis() - 300000, person)
728 .addMessage("Is it me you're looking for?",
729 SystemClock.currentThreadTimeMillis(), person)
730 )
731 .setActions(replyAction)
732 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldsc76888d2020-05-04 15:36:09 -0400733 .setShortcutId(VALID_CONVO_SHORTCUT_ID)
Mady Mellor9e923e12019-12-17 16:08:46 -0800734 .setGroupSummary(isSummary);
735 if (groupKey != null) {
736 nb.setGroup(groupKey);
737 }
738 if (addBubbleMetadata) {
Mady Mellora92268c2020-03-09 17:25:08 -0700739 nb.setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -0800740 }
741 return nb;
742 }
743
Mady Mellora92268c2020-03-09 17:25:08 -0700744 private Notification.BubbleMetadata getBubbleMetadata() {
745 PendingIntent pendingIntent = mock(PendingIntent.class);
746 Intent intent = mock(Intent.class);
747 when(pendingIntent.getIntent()).thenReturn(intent);
748
749 ActivityInfo info = new ActivityInfo();
750 info.resizeMode = RESIZE_MODE_RESIZEABLE;
751 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
752
753 return new Notification.BubbleMetadata.Builder(
754 pendingIntent,
755 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
756 .build();
757 }
758
Mady Mellor22f2f072019-04-18 13:26:18 -0700759 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
760 throws RemoteException {
761
Mady Mellor9e923e12019-12-17 16:08:46 -0800762 String groupKey = "BUBBLE_GROUP";
Mady Mellor22f2f072019-04-18 13:26:18 -0700763
Mady Mellor9e923e12019-12-17 16:08:46 -0800764 // Notification that has bubble metadata
765 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
766 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
Mady Mellor22f2f072019-04-18 13:26:18 -0700767
Julia Reynolds24edc002020-01-29 16:35:32 -0500768 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
769 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
770 nrBubble.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700771 waitForIdle();
772
773 // Make sure we are a bubble
774 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
775 assertEquals(1, notifsAfter.length);
776 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
777
Mady Mellor9e923e12019-12-17 16:08:46 -0800778 // Notification without bubble metadata
779 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
780 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
781
Julia Reynolds24edc002020-01-29 16:35:32 -0500782 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
783 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
784 nrPlain.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700785 waitForIdle();
786
787 notifsAfter = mBinderService.getActiveNotifications(PKG);
788 assertEquals(2, notifsAfter.length);
789
790 // Summary notification for both of those
Mady Mellor9e923e12019-12-17 16:08:46 -0800791 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
792 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
793
Mady Mellor22f2f072019-04-18 13:26:18 -0700794 if (summaryAutoCancel) {
795 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
796 }
Julia Reynolds24edc002020-01-29 16:35:32 -0500797 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
798 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
799 nrSummary.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700800 waitForIdle();
801
802 notifsAfter = mBinderService.getActiveNotifications(PKG);
803 assertEquals(3, notifsAfter.length);
804
805 return nrSummary;
806 }
807
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500808 @Test
Jay Aliomerfea80252019-11-20 18:14:24 -0500809 public void testDefaultAssistant_overrideDefault() {
810 final int userId = 0;
811 final String testComponent = "package/class";
812 final List<UserInfo> userInfos = new ArrayList<>();
813 userInfos.add(new UserInfo(0, "", 0));
814 final ArraySet<ComponentName> validAssistants = new ArraySet<>();
815 validAssistants.add(ComponentName.unflattenFromString(testComponent));
Jay Aliomerfea80252019-11-20 18:14:24 -0500816 when(mActivityManager.isLowRamDevice()).thenReturn(false);
817 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
818 .thenReturn(validAssistants);
Jay Aliomer76e1f2722020-03-05 12:36:38 -0500819 when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
Jay Aliomerfea80252019-11-20 18:14:24 -0500820 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
821
822 mService.setDefaultAssistantForUser(userId);
823
824 verify(mAssistants).setPackageOrComponentEnabled(
825 eq(testComponent), eq(userId), eq(true), eq(true));
Jay Aliomerfea80252019-11-20 18:14:24 -0500826 }
827
828 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500829 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500830 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500831 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400832 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500833 new ParceledListSlice(Arrays.asList(channel)));
834 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400835 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500836 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500837 }
838
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500839 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500840 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500841 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400842 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200843 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500844 fail("Exception should be thrown immediately.");
845 } catch (NullPointerException e) {
846 // pass
847 }
848 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500849
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500850 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500851 public void testCreateNotificationChannels_TwoChannels() throws Exception {
852 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500853 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500854 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500855 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400856 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500857 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400858 assertTrue(mBinderService.getNotificationChannel(
859 PKG, mContext.getUserId(), PKG, "id1") != null);
860 assertTrue(mBinderService.getNotificationChannel(
861 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500862 }
863
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500864 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400865 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
866 throws Exception {
867 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500868 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400869 mBinderService.createNotificationChannels(PKG,
870 new ParceledListSlice(Arrays.asList(channel)));
871
872 // Recreating the channel doesn't throw, but ignores importance.
873 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400874 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400875 mBinderService.createNotificationChannels(PKG,
876 new ParceledListSlice(Arrays.asList(dupeChannel)));
877 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400878 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500879 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400880 }
881
882 @Test
883 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
884 throws Exception {
885 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500886 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400887 mBinderService.createNotificationChannels(PKG,
888 new ParceledListSlice(Arrays.asList(channel)));
889
890 // Recreating with a lower importance is allowed to modify the channel.
891 final NotificationChannel dupeChannel =
892 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
893 mBinderService.createNotificationChannels(PKG,
894 new ParceledListSlice(Arrays.asList(dupeChannel)));
895 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400896 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400897 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
898 }
899
900 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400901 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
902 throws Exception {
903 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500904 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400905 mBinderService.createNotificationChannels(PKG,
906 new ParceledListSlice(Arrays.asList(channel)));
907
908 // The user modifies importance directly, can no longer be changed by the app.
909 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400910 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400911 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
912
913 // Recreating with a lower importance leaves channel unchanged.
914 final NotificationChannel dupeChannel =
915 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
916 mBinderService.createNotificationChannels(PKG,
917 new ParceledListSlice(Arrays.asList(dupeChannel)));
918 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400919 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400920 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400921 }
922
923 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500924 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
925 throws Exception {
926 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500927 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500928 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400929 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400930 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500931 new ParceledListSlice(Arrays.asList(channel1, channel2)));
932 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400933 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500934 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500935 }
936
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500937 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500938 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500939 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
940
941 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400942 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500943 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400944
945 // isBlocked is only used for user blocking, not app suspension
946 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500947 }
948
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500949 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500950 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500951 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
952
953 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400954 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500955 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400956 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400957 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400958
959 mBinderService.createNotificationChannels(
960 PKG, new ParceledListSlice(Arrays.asList(channel)));
Julia Reynolds24edc002020-01-29 16:35:32 -0500961 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400962 mBinderService.enqueueNotificationWithTag(PKG, PKG,
963 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400964 sbn.getId(), sbn.getNotification(), sbn.getUserId());
965 waitForIdle();
966 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
967 }
968
969 @Test
970 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
971 throws Exception {
972 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
973
974 NotificationChannel channel = new NotificationChannel("blocked", "name",
975 NotificationManager.IMPORTANCE_NONE);
976 mBinderService.createNotificationChannels(
977 PKG, new ParceledListSlice(Arrays.asList(channel)));
978
Julia Reynolds24edc002020-01-29 16:35:32 -0500979 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -0400980 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400981 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400982 sbn.getId(), sbn.getNotification(), sbn.getUserId());
983 waitForIdle();
984 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
985 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400986 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400987 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
988 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400989 }
990
991 @Test
992 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
993 throws Exception {
994 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
995
996 NotificationChannel channel =
997 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
998 mBinderService.createNotificationChannels(
999 PKG, new ParceledListSlice(Arrays.asList(channel)));
1000
1001 NotificationChannel update =
1002 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1003 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1004 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001005 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1006 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001007
Julia Reynolds24edc002020-01-29 16:35:32 -05001008 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001009 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001010 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001011 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1012 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001013 // The first time a foreground service notification is shown, we allow the channel
1014 // to be updated to allow it to be seen.
1015 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1016 assertEquals(IMPORTANCE_LOW,
1017 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001018 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1019 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -04001020 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001021 waitForIdle();
1022
1023 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1024 update.setFgServiceShown(true);
1025 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1026 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001027 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1028 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001029
Julia Reynolds24edc002020-01-29 16:35:32 -05001030 sbn = generateNotificationRecord(channel).getSbn();
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001031 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001032 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1033 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001034 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1035 waitForIdle();
1036 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001037 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001038 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001039 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1040 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001041 }
1042
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001043 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -04001044 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1045 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001046 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001047 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1048 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -04001049
1050 NotificationChannel channel = new NotificationChannel("id", "name",
1051 NotificationManager.IMPORTANCE_HIGH);
1052 channel.setGroup("something");
1053 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -04001054 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -04001055 verify(mUsageStats, times(1)).registerBlocked(eq(r));
1056 }
1057
1058 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -04001059 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001060 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1061
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001062 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -04001063
Julia Reynolds24edc002020-01-29 16:35:32 -05001064 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001065 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1066 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -04001067 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1068 waitForIdle();
1069 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001070 }
1071
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001072 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001073 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1074 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1075
1076 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1077
Julia Reynolds24edc002020-01-29 16:35:32 -05001078 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001079 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001080 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1081 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001082 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1083 waitForIdle();
1084 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001085 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001086 }
1087
Brad Stenning8c991ea2018-07-31 13:33:01 -07001088 /**
1089 * Confirm the system user on automotive devices can use car categories
1090 */
1091 @Test
1092 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
1093 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1094 .thenReturn(true);
1095 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1096 Notification.CATEGORY_CAR_WARNING,
1097 Notification.CATEGORY_CAR_INFORMATION);
1098 int id = 0;
1099 for (String category: categories) {
1100 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001101 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001102 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001103 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1104 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001105 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1106 }
1107 waitForIdle();
1108 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1109 }
1110
1111
1112 /**
1113 * Confirm restricted notification categories only apply to automotive.
1114 */
1115 @Test
1116 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1117 mService.isSystemUid = false;
1118 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1119 .thenReturn(false);
1120 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1121 Notification.CATEGORY_CAR_WARNING,
1122 Notification.CATEGORY_CAR_INFORMATION);
1123 int id = 0;
1124 for (String category: categories) {
1125 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001126 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001127 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001128 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1129 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001130 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1131 }
1132 waitForIdle();
1133 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1134 }
1135
1136 /**
1137 * Confirm if a non-system user tries to use the car categories on a automotive device that
1138 * they will get a security exception
1139 */
1140 @Test
1141 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1142 mService.isSystemUid = false;
1143 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1144 .thenReturn(true);
1145 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1146 Notification.CATEGORY_CAR_WARNING,
1147 Notification.CATEGORY_CAR_INFORMATION);
1148 for (String category: categories) {
Julia Reynolds24edc002020-01-29 16:35:32 -05001149 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001150 sbn.getNotification().category = category;
1151 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001152 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1153 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001154 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1155 fail("Calls from non system apps should not allow use of restricted categories");
1156 } catch (SecurityException e) {
1157 // pass
1158 }
1159 }
1160 waitForIdle();
1161 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1162 }
1163
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001164 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001165 public void testBlockedNotifications_blockedByAssistant() throws Exception {
1166 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001167 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001168
1169 NotificationChannel channel = new NotificationChannel("id", "name",
1170 NotificationManager.IMPORTANCE_HIGH);
1171 NotificationRecord r = generateNotificationRecord(channel);
1172 mService.addEnqueuedNotification(r);
1173
Julia Reynolds27c0a962018-12-10 12:37:28 -05001174 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001175 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001176 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05001177 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05001178 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001179
1180 NotificationManagerService.PostNotificationRunnable runnable =
1181 mService.new PostNotificationRunnable(r.getKey());
1182 runnable.run();
1183 waitForIdle();
1184
1185 verify(mUsageStats, never()).registerPostedByApp(any());
1186 }
1187
1188 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001189 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001190 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1191 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001192 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001193 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001194 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001195 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001196 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001197 }
1198
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001199 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001200 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
Will Brockman2b6959e2020-01-22 09:59:50 -05001201 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1202 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1203 generateNotificationRecord(null).getNotification(), 0);
1204 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001205 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001206
Will Brockman2b6959e2020-01-22 09:59:50 -05001207 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
Will Brockman9918db92020-03-06 16:48:39 -05001208 assertTrue(call.wasLogged);
Will Brockman75c60572020-01-31 10:30:27 -05001209 assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1210 call.event);
Will Brockman2b6959e2020-01-22 09:59:50 -05001211 assertNotNull(call.r);
1212 assertNull(call.old);
1213 assertEquals(0, call.position);
1214 assertEquals(0, call.buzzBeepBlink);
Julia Reynolds24edc002020-01-29 16:35:32 -05001215 assertEquals(PKG, call.r.getSbn().getPackageName());
1216 assertEquals(0, call.r.getSbn().getId());
1217 assertEquals(tag, call.r.getSbn().getTag());
Will Brockman4f0f9d22020-02-23 21:18:11 -05001218 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order
Will Brockman2b6959e2020-01-22 09:59:50 -05001219 }
1220
1221 @Test
1222 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1223 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1224 Notification original = new Notification.Builder(mContext,
1225 mTestNotificationChannel.getId())
1226 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1227 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1228 Notification update = new Notification.Builder(mContext,
1229 mTestNotificationChannel.getId())
1230 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1231 .setCategory(Notification.CATEGORY_ALARM).build();
1232 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1233 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001234 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001235
Will Brockman9918db92020-03-06 16:48:39 -05001236 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001237 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001238 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001239 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001240 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001241
Will Brockman9918db92020-03-06 16:48:39 -05001242 assertTrue(mNotificationRecordLogger.get(1).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001243 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001244 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED,
Will Brockman9918db92020-03-06 16:48:39 -05001245 mNotificationRecordLogger.event(1));
Will Brockmancfd98302020-01-29 15:57:30 -05001246 // Instance ID doesn't change on update of an active notification
Will Brockman4f0f9d22020-02-23 21:18:11 -05001247 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman2b6959e2020-01-22 09:59:50 -05001248 }
1249
1250 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001251 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1252 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
Will Brockman2b6959e2020-01-22 09:59:50 -05001253 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1254 generateNotificationRecord(null).getNotification(), 0);
1255 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1256 generateNotificationRecord(null).getNotification(), 0);
1257 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001258 assertEquals(2, mNotificationRecordLogger.numCalls());
1259 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockmand3d49332020-02-10 19:43:03 -05001260 assertEquals(
1261 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001262 mNotificationRecordLogger.event(0));
1263 assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1264 assertNull(mNotificationRecordLogger.event(1));
Will Brockmand3d49332020-02-10 19:43:03 -05001265 }
1266
1267 @Test
1268 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1269 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1270 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1271 generateNotificationRecord(null).getNotification(),
1272 0);
1273 final Notification notif = generateNotificationRecord(null).getNotification();
1274 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1275 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1276 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001277 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001278 assertEquals(
1279 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001280 mNotificationRecordLogger.event(0));
1281 assertNull(mNotificationRecordLogger.event(1));
Will Brockman2b6959e2020-01-22 09:59:50 -05001282 }
1283
1284 @Test
Will Brockmancfd98302020-01-29 15:57:30 -05001285 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1286 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1287 Notification notification = new Notification.Builder(mContext,
1288 mTestNotificationChannel.getId())
1289 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1290 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1291 waitForIdle();
1292 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1293 waitForIdle();
1294 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1295 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001296 assertEquals(3, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001297
Will Brockmancfd98302020-01-29 15:57:30 -05001298 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001299 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001300 mNotificationRecordLogger.event(0));
1301 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman4f0f9d22020-02-23 21:18:11 -05001302 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001303
Will Brockmancfd98302020-01-29 15:57:30 -05001304 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001305 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
Will Brockman9918db92020-03-06 16:48:39 -05001306 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001307 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001308
1309 assertEquals(
1310 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001311 mNotificationRecordLogger.event(2));
1312 assertTrue(mNotificationRecordLogger.get(2).wasLogged);
Will Brockmancfd98302020-01-29 15:57:30 -05001313 // New instance ID because notification was canceled before re-post
Will Brockman4f0f9d22020-02-23 21:18:11 -05001314 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001315 }
1316
1317 @Test
1318 public void testCancelNonexistentNotification() throws Exception {
1319 mBinderService.cancelNotificationWithTag(PKG, PKG,
1320 "testCancelNonexistentNotification", 0, 0);
1321 waitForIdle();
1322 // The notification record logger doesn't even get called when a nonexistent notification
1323 // is cancelled, because that happens very frequently and is not interesting.
Will Brockman9918db92020-03-06 16:48:39 -05001324 assertEquals(0, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001325 }
1326
1327 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001328 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001329 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1330 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001331 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001332 mBinderService.cancelNotificationWithTag(PKG, PKG,
1333 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001334 waitForIdle();
1335 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001336 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001337 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001338 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001339 }
1340
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001341 @Test
Evan Lairdd04af512020-01-09 11:18:09 -05001342 public void testPostCancelPostNotifiesListeners() throws Exception {
1343 // WHEN a notification is posted
1344 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1345 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1346 sbn.getNotification(), sbn.getUserId());
Evan Laird131d38b2020-06-24 23:40:30 -04001347 Thread.sleep(1); // make sure the system clock advances before the next step
Evan Lairdd04af512020-01-09 11:18:09 -05001348 // THEN it is canceled
1349 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Evan Laird131d38b2020-06-24 23:40:30 -04001350 Thread.sleep(1); // here too
Evan Lairdd04af512020-01-09 11:18:09 -05001351 // THEN it is posted again (before the cancel has a chance to finish)
1352 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1353 sbn.getNotification(), sbn.getUserId());
1354 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
1355 waitForIdle();
1356
1357 // The final enqueue made it to the listener instead of being canceled
1358 StatusBarNotification[] notifs =
1359 mBinderService.getActiveNotifications(PKG);
1360 assertEquals(1, notifs.length);
1361 assertEquals(1, mService.getNotificationRecordCount());
1362 }
1363
1364 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001365 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001366 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1367 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001368 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001369 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001370 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1371 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001372 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001373 mBinderService.cancelNotificationWithTag(PKG, PKG,
1374 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001375 waitForIdle();
1376 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001377 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001378 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001379 assertEquals(0, mService.getNotificationRecordCount());
1380 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1381 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1382 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001383 }
1384
1385 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001386 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001387 NotificationRecord r = generateNotificationRecord(null);
Julia Reynolds24edc002020-01-29 16:35:32 -05001388 final StatusBarNotification sbn = r.getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001389 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1390 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001391 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001392 mBinderService.cancelNotificationsFromListener(null, null);
1393 waitForIdle();
1394 StatusBarNotification[] notifs =
1395 mBinderService.getActiveNotifications(sbn.getPackageName());
1396 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001397 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001398 }
1399
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001400 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001401 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001402 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001403 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1404 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001405 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001406 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001407 waitForIdle();
1408 StatusBarNotification[] notifs =
1409 mBinderService.getActiveNotifications(sbn.getPackageName());
1410 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001411 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001412 }
1413
1414 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001415 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1416 throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001417 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001418 sbn.getNotification().flags =
1419 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1420 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1421 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1422 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1423 waitForIdle();
1424 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1425 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1426 }
1427
1428 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001429 public void testUserInitiatedClearAll_noLeak() throws Exception {
1430 final NotificationRecord n = generateNotificationRecord(
1431 mTestNotificationChannel, 1, "group", true);
1432
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001433 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1434 "testUserInitiatedClearAll_noLeak",
Julia Reynolds24edc002020-01-29 16:35:32 -05001435 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001436 waitForIdle();
1437
Julia Reynolds503ed942017-10-04 16:04:56 -04001438 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001439 n.getUserId());
1440 waitForIdle();
1441 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001442 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
Julia Reynolds080361e2017-07-13 11:23:12 -04001443 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001444 assertEquals(0, mService.getNotificationRecordCount());
1445 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1446 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1447 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001448 }
1449
1450 @Test
1451 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1452 final NotificationRecord parent = generateNotificationRecord(
1453 mTestNotificationChannel, 1, "group1", true);
1454 final NotificationRecord child = generateNotificationRecord(
1455 mTestNotificationChannel, 2, "group1", false);
1456
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001457 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1458 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001459 parent.getSbn().getId(), parent.getSbn().getNotification(),
1460 parent.getSbn().getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001461 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1462 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001463 child.getSbn().getId(), child.getSbn().getNotification(),
1464 child.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001465 waitForIdle();
1466
Julia Reynolds24edc002020-01-29 16:35:32 -05001467 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001468 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001469 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001470 }
1471
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001472 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001473 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001474 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds0839c022017-06-15 15:24:01 -04001475 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001476 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1477 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001478 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1479 }
1480 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1481 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001482
Julia Reynolds503ed942017-10-04 16:04:56 -04001483 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001484 }
1485
1486 @Test
1487 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1488 final NotificationRecord parent = generateNotificationRecord(
1489 mTestNotificationChannel, 1, "group1", true);
1490 final NotificationRecord parentAsChild = generateNotificationRecord(
1491 mTestNotificationChannel, 1, "group1", false);
1492 final NotificationRecord child = generateNotificationRecord(
1493 mTestNotificationChannel, 2, "group1", false);
1494
1495 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001496 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1497 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001498 parent.getSbn().getId(), parent.getSbn().getNotification(),
1499 parent.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001500 waitForIdle();
1501
1502 // enqueue the child several times
1503 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001504 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1505 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001506 child.getSbn().getId(), child.getSbn().getNotification(),
1507 child.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001508 }
1509 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001510 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1511 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001512 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
1513 parentAsChild.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001514 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001515
Julia Reynolds503ed942017-10-04 16:04:56 -04001516 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001517 }
1518
1519 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001520 public void testAutobundledSummary_notificationAdded() {
1521 NotificationRecord summary =
1522 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1523 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1524 mService.addNotification(summary);
1525 mService.mSummaryByGroupKey.put("pkg", summary);
1526 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1527 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001528 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001529
Julia Reynolds24edc002020-01-29 16:35:32 -05001530 assertTrue(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001531 }
1532
1533 @Test
1534 public void testAutobundledSummary_notificationRemoved() {
1535 NotificationRecord summary =
1536 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1537 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1538 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1539 mService.addNotification(summary);
1540 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1541 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1542 mService.mSummaryByGroupKey.put("pkg", summary);
1543
Mady Mellor6d775f82019-11-12 16:12:19 -08001544 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001545
Julia Reynolds24edc002020-01-29 16:35:32 -05001546 assertFalse(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001547 }
1548
1549 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001550 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001551 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001552 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001553 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1554 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001555 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001556 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001557 waitForIdle();
1558 StatusBarNotification[] notifs =
1559 mBinderService.getActiveNotifications(sbn.getPackageName());
1560 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001561 assertEquals(1, 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_IgnoreOtherPackages() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001566 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001567 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001568 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1569 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001570 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001571 mBinderService.cancelAllNotifications("other_pkg_name", 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 }
1578
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001579 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001580 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001581 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001582 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1583 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001584 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001585 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1586 waitForIdle();
1587 StatusBarNotification[] notifs =
1588 mBinderService.getActiveNotifications(sbn.getPackageName());
1589 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001590 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001591 }
1592
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001593 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001594 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001595 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001596 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1597 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001598 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001599 // Null pkg is how we signal a user switch.
1600 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1601 waitForIdle();
1602 StatusBarNotification[] notifs =
1603 mBinderService.getActiveNotifications(sbn.getPackageName());
1604 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001605 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001606 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001607
1608 @Test
Beverly40239d92017-07-07 10:20:41 -04001609 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001610 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Beverly40239d92017-07-07 10:20:41 -04001611 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001612 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1613 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001614 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1615 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1616 waitForIdle();
1617 StatusBarNotification[] notifs =
1618 mBinderService.getActiveNotifications(sbn.getPackageName());
1619 assertEquals(0, notifs.length);
1620 }
1621
1622 @Test
1623 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1624 final NotificationRecord notif = generateNotificationRecord(
1625 mTestNotificationChannel, 1, "group", true);
1626 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001627 mService.addNotification(notif);
1628 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001629 notif.getUserId(), 0, null);
1630 waitForIdle();
1631 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001632 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001633 assertEquals(0, notifs.length);
1634 }
1635
1636 @Test
1637 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1638 final NotificationRecord notif = generateNotificationRecord(
1639 mTestNotificationChannel, 1, "group", true);
1640 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001641 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001642
Julia Reynolds503ed942017-10-04 16:04:56 -04001643 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001644 notif.getUserId());
1645 waitForIdle();
1646 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001647 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001648 assertEquals(1, notifs.length);
1649 }
1650
1651 @Test
1652 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1653 final NotificationRecord parent = generateNotificationRecord(
1654 mTestNotificationChannel, 1, "group", true);
1655 final NotificationRecord child = generateNotificationRecord(
1656 mTestNotificationChannel, 2, "group", false);
1657 final NotificationRecord child2 = generateNotificationRecord(
1658 mTestNotificationChannel, 3, "group", false);
1659 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1660 final NotificationRecord newGroup = generateNotificationRecord(
1661 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001662 mService.addNotification(parent);
1663 mService.addNotification(child);
1664 mService.addNotification(child2);
1665 mService.addNotification(newGroup);
1666 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001667 waitForIdle();
1668 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001669 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001670 assertEquals(1, notifs.length);
1671 }
1672
1673 @Test
1674 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1675 final NotificationRecord parent = generateNotificationRecord(
1676 mTestNotificationChannel, 1, "group", true);
1677 final NotificationRecord child = generateNotificationRecord(
1678 mTestNotificationChannel, 2, "group", false);
1679 final NotificationRecord child2 = generateNotificationRecord(
1680 mTestNotificationChannel, 3, "group", false);
1681 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1682 final NotificationRecord newGroup = generateNotificationRecord(
1683 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001684 mService.addNotification(parent);
1685 mService.addNotification(child);
1686 mService.addNotification(child2);
1687 mService.addNotification(newGroup);
1688 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001689 parent.getUserId());
1690 waitForIdle();
1691 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001692 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001693 assertEquals(1, notifs.length);
1694 }
1695
1696 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001697 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001698 Notification n =
1699 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1700 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1701 .build();
1702 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04001703 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001704 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001705 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001706 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001707 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1708 sbn.getUserId());
1709 waitForIdle();
1710 StatusBarNotification[] notifs =
1711 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001712 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001713 }
1714
1715 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001716 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001717 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001718 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001719 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001720 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001721 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1722 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001723 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001724 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001725 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1726 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001727 waitForIdle();
1728 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001729 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001730 }
1731
1732 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001733 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1734 throws Exception {
1735 final NotificationRecord parent = generateNotificationRecord(
1736 mTestNotificationChannel, 1, "group", true);
1737 final NotificationRecord child = generateNotificationRecord(
1738 mTestNotificationChannel, 2, "group", false);
1739 final NotificationRecord child2 = generateNotificationRecord(
1740 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001741 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001742 final NotificationRecord newGroup = generateNotificationRecord(
1743 mTestNotificationChannel, 4, "group2", false);
1744 mService.addNotification(parent);
1745 mService.addNotification(child);
1746 mService.addNotification(child2);
1747 mService.addNotification(newGroup);
1748 mService.getBinderService().cancelNotificationsFromListener(null, null);
1749 waitForIdle();
1750 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001751 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001752 assertEquals(0, notifs.length);
1753 }
1754
1755 @Test
1756 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1757 throws Exception {
1758 final NotificationRecord parent = generateNotificationRecord(
1759 mTestNotificationChannel, 1, "group", true);
1760 final NotificationRecord child = generateNotificationRecord(
1761 mTestNotificationChannel, 2, "group", false);
1762 final NotificationRecord child2 = generateNotificationRecord(
1763 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001764 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001765 final NotificationRecord newGroup = generateNotificationRecord(
1766 mTestNotificationChannel, 4, "group2", false);
1767 mService.addNotification(parent);
1768 mService.addNotification(child);
1769 mService.addNotification(child2);
1770 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001771 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1772 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001773 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1774 waitForIdle();
1775 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001776 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001777 assertEquals(1, notifs.length);
1778 }
1779
1780 @Test
1781 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1782 final NotificationRecord parent = generateNotificationRecord(
1783 mTestNotificationChannel, 1, "group", true);
1784 final NotificationRecord child = generateNotificationRecord(
1785 mTestNotificationChannel, 2, "group", false);
1786 final NotificationRecord child2 = generateNotificationRecord(
1787 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001788 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001789 final NotificationRecord newGroup = generateNotificationRecord(
1790 mTestNotificationChannel, 4, "group2", false);
1791 mService.addNotification(parent);
1792 mService.addNotification(child);
1793 mService.addNotification(child2);
1794 mService.addNotification(newGroup);
1795 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1796 parent.getUserId());
1797 waitForIdle();
1798 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001799 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001800 assertEquals(0, notifs.length);
1801 }
1802
1803 @Test
Will Brockman8da8c8e2020-04-30 12:46:15 -04001804 public void testGroupInstanceIds() throws Exception {
1805 final NotificationRecord group1 = generateNotificationRecord(
1806 mTestNotificationChannel, 1, "group1", true);
1807 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1808 group1.getSbn().getId(), group1.getSbn().getNotification(),
1809 group1.getSbn().getUserId());
1810 waitForIdle();
1811
1812 // same group, child, should be returned
1813 final NotificationRecord group1Child = generateNotificationRecord(
1814 mTestNotificationChannel, 2, "group1", false);
1815 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1816 group1Child.getSbn().getId(),
1817 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
1818 waitForIdle();
1819
1820 assertEquals(2, mNotificationRecordLogger.numCalls());
1821 assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
1822 mNotificationRecordLogger.get(1).groupInstanceId.getId());
1823 }
1824
1825 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001826 public void testFindGroupNotificationsLocked() throws Exception {
1827 // make sure the same notification can be found in both lists and returned
1828 final NotificationRecord group1 = generateNotificationRecord(
1829 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001830 mService.addEnqueuedNotification(group1);
1831 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001832
1833 // should not be returned
1834 final NotificationRecord group2 = generateNotificationRecord(
1835 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001836 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001837 group2.getSbn().getId(), group2.getSbn().getNotification(),
1838 group2.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001839 waitForIdle();
1840
1841 // should not be returned
1842 final NotificationRecord nonGroup = generateNotificationRecord(
1843 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001844 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001845 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
1846 nonGroup.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001847 waitForIdle();
1848
1849 // same group, child, should be returned
1850 final NotificationRecord group1Child = generateNotificationRecord(
1851 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001852 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001853 group1Child.getSbn().getId(),
1854 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001855 waitForIdle();
1856
1857 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001858 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynolds24edc002020-01-29 16:35:32 -05001859 group1.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001860 assertEquals(3, inGroup1.size());
1861 for (NotificationRecord record : inGroup1) {
1862 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
Julia Reynolds24edc002020-01-29 16:35:32 -05001863 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001864 }
1865 }
1866
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001867 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001868 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1869 final NotificationRecord notif = generateNotificationRecord(
1870 mTestNotificationChannel, 1, "group", true);
1871 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1872 mService.addNotification(notif);
1873 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1874 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1875 waitForIdle();
1876 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001877 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001878 assertEquals(0, notifs.length);
1879 }
1880
1881 @Test
1882 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1883 throws Exception {
1884 final NotificationRecord parent = generateNotificationRecord(
1885 mTestNotificationChannel, 1, "group", true);
1886 final NotificationRecord child = generateNotificationRecord(
1887 mTestNotificationChannel, 2, "group", false);
1888 final NotificationRecord child2 = generateNotificationRecord(
1889 mTestNotificationChannel, 3, "group", false);
1890 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1891 final NotificationRecord newGroup = generateNotificationRecord(
1892 mTestNotificationChannel, 4, "group2", false);
1893 mService.addNotification(parent);
1894 mService.addNotification(child);
1895 mService.addNotification(child2);
1896 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001897 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1898 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001899 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1900 waitForIdle();
1901 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001902 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001903 assertEquals(0, notifs.length);
1904 }
1905
1906 @Test
1907 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001908 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds40f00d72017-12-12 10:47:32 -05001909 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001910 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1911 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001912 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1913 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1914 waitForIdle();
1915 StatusBarNotification[] notifs =
1916 mBinderService.getActiveNotifications(sbn.getPackageName());
1917 assertEquals(0, notifs.length);
1918 }
1919
1920 @Test
1921 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1922 final NotificationRecord notif = generateNotificationRecord(
1923 mTestNotificationChannel, 1, "group", true);
1924 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1925 mService.addNotification(notif);
1926 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1927 notif.getUserId(), 0, null);
1928 waitForIdle();
1929 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001930 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001931 assertEquals(0, notifs.length);
1932 }
1933
1934 @Test
1935 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1936 final NotificationRecord notif = generateNotificationRecord(
1937 mTestNotificationChannel, 1, "group", true);
1938 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1939 mService.addNotification(notif);
1940
1941 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1942 notif.getUserId());
1943 waitForIdle();
1944 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001945 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001946 assertEquals(1, notifs.length);
1947 }
1948
1949 @Test
1950 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1951 final NotificationRecord parent = generateNotificationRecord(
1952 mTestNotificationChannel, 1, "group", true);
1953 final NotificationRecord child = generateNotificationRecord(
1954 mTestNotificationChannel, 2, "group", false);
1955 final NotificationRecord child2 = generateNotificationRecord(
1956 mTestNotificationChannel, 3, "group", false);
1957 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1958 final NotificationRecord newGroup = generateNotificationRecord(
1959 mTestNotificationChannel, 4, "group2", false);
1960 mService.addNotification(parent);
1961 mService.addNotification(child);
1962 mService.addNotification(child2);
1963 mService.addNotification(newGroup);
1964 mService.getBinderService().cancelNotificationsFromListener(null, null);
1965 waitForIdle();
1966 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001967 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001968 assertEquals(1, notifs.length);
1969 }
1970
1971 @Test
1972 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1973 throws Exception {
1974 final NotificationRecord parent = generateNotificationRecord(
1975 mTestNotificationChannel, 1, "group", true);
1976 final NotificationRecord child = generateNotificationRecord(
1977 mTestNotificationChannel, 2, "group", false);
1978 final NotificationRecord child2 = generateNotificationRecord(
1979 mTestNotificationChannel, 3, "group", false);
1980 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1981 final NotificationRecord newGroup = generateNotificationRecord(
1982 mTestNotificationChannel, 4, "group2", false);
1983 mService.addNotification(parent);
1984 mService.addNotification(child);
1985 mService.addNotification(child2);
1986 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001987 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1988 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001989 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1990 waitForIdle();
1991 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001992 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001993 assertEquals(0, notifs.length);
1994 }
1995
1996 @Test
1997 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1998 final NotificationRecord parent = generateNotificationRecord(
1999 mTestNotificationChannel, 1, "group", true);
2000 final NotificationRecord child = generateNotificationRecord(
2001 mTestNotificationChannel, 2, "group", false);
2002 final NotificationRecord child2 = generateNotificationRecord(
2003 mTestNotificationChannel, 3, "group", false);
2004 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2005 final NotificationRecord newGroup = generateNotificationRecord(
2006 mTestNotificationChannel, 4, "group2", false);
2007 mService.addNotification(parent);
2008 mService.addNotification(child);
2009 mService.addNotification(child2);
2010 mService.addNotification(newGroup);
2011 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2012 parent.getUserId());
2013 waitForIdle();
2014 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002015 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002016 assertEquals(1, notifs.length);
2017 }
2018
2019 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002020 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002021 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002022 mService.setPreferencesHelper(mPreferencesHelper);
2023 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002024 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002025 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002026
Julia Reynoldsbad42972017-04-25 13:52:49 -04002027 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002028 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04002029 generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002030 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
2031 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002032 }
2033
2034 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002035 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002036 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002037 mService.setPreferencesHelper(mPreferencesHelper);
2038 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002039 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05002040 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002041
Julia Reynoldsbad42972017-04-25 13:52:49 -04002042 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002043 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
2044 0, generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002045 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
Julia Reynolds0f767342019-12-18 09:11:55 -05002046 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002047 anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002048 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002049
2050 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002051 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002052 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002053
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002054 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002055 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2056 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2057
2058 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2059 captor.getValue().getAction());
2060 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002061 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2062 }
2063
2064 @Test
2065 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
2066 mService.setPreferencesHelper(mPreferencesHelper);
2067
2068 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
2069 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002070 }
2071
2072 @Test
2073 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002074 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002075
2076 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
2077 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2078 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2079
2080 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2081 captor.getValue().getAction());
2082 assertEquals(PKG, captor.getValue().getPackage());
2083 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2084 }
2085
2086 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002087 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002088 mService.setPreferencesHelper(mPreferencesHelper);
2089 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002090 eq(mTestNotificationChannel.getId()), anyBoolean()))
2091 .thenReturn(mTestNotificationChannel);
2092
2093 NotificationChannel updatedChannel =
2094 new NotificationChannel(mTestNotificationChannel.getId(),
2095 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
2096
2097 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
2098 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2099 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2100
2101 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2102 captor.getValue().getAction());
2103 assertEquals(PKG, captor.getValue().getPackage());
2104 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002105 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002106 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2107 }
2108
2109 @Test
2110 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
2111 NotificationChannel existingChannel =
2112 new NotificationChannel(mTestNotificationChannel.getId(),
2113 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002114 mService.setPreferencesHelper(mPreferencesHelper);
2115 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002116 eq(mTestNotificationChannel.getId()), anyBoolean()))
2117 .thenReturn(existingChannel);
2118
2119 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2120 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2121 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2122
2123 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2124 captor.getValue().getAction());
2125 assertEquals(PKG, captor.getValue().getPackage());
2126 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002127 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002128 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2129 }
2130
2131 @Test
2132 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
2133 NotificationChannel existingChannel =
2134 new NotificationChannel(mTestNotificationChannel.getId(),
2135 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002136 mService.setPreferencesHelper(mPreferencesHelper);
2137 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002138 eq(mTestNotificationChannel.getId()), anyBoolean()))
2139 .thenReturn(existingChannel);
2140
2141 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2142 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2143 }
2144
2145 @Test
2146 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
2147 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002148 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002149 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2150 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002151 .thenReturn(existing);
2152
2153 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
2154 updated.setBlocked(true);
2155
2156 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
2157 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2158 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2159
2160 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2161 captor.getValue().getAction());
2162 assertEquals(PKG, captor.getValue().getPackage());
2163 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002164 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002165 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2166 }
2167
2168 @Test
2169 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
2170 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2171 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002172 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002173 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2174 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002175 .thenReturn(existing);
2176
2177 mBinderService.updateNotificationChannelGroupForPackage(
2178 PKG, 0, new NotificationChannelGroup("id", "name"));
2179 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2180 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2181
2182 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2183 captor.getValue().getAction());
2184 assertEquals(PKG, captor.getValue().getPackage());
2185 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002186 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002187 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2188 }
2189
2190 @Test
2191 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
2192 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002193 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002194 when(mPreferencesHelper.getNotificationChannelGroup(
2195 eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002196 .thenReturn(existing);
2197
2198 mBinderService.updateNotificationChannelGroupForPackage(
2199 PKG, 0, new NotificationChannelGroup("id", "new name"));
2200 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2201 }
2202
2203 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002204 public void testCreateChannelNotifyListener() throws Exception {
2205 List<String> associations = new ArrayList<>();
2206 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002207 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2208 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002209 mService.setPreferencesHelper(mPreferencesHelper);
2210 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002211 eq(mTestNotificationChannel.getId()), anyBoolean()))
2212 .thenReturn(mTestNotificationChannel);
2213 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002214 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002215 eq(channel2.getId()), anyBoolean()))
2216 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002217 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
2218 eq(channel2), anyBoolean(), anyBoolean()))
2219 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002220
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002221 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002222 mBinderService.createNotificationChannels(PKG,
2223 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002224 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002225 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002226 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002227 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002228 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002229 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2230 }
2231
2232 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002233 public void testCreateChannelGroupNotifyListener() throws Exception {
2234 List<String> associations = new ArrayList<>();
2235 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002236 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2237 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002238 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002239 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
2240 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
2241
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002242 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002243 mBinderService.createNotificationChannelGroups(PKG,
2244 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002245 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002246 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002247 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002248 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002249 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002250 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2251 }
2252
2253 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002254 public void testUpdateChannelNotifyListener() throws Exception {
2255 List<String> associations = new ArrayList<>();
2256 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002257 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2258 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002259 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002260 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002261 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002262 eq(mTestNotificationChannel.getId()), anyBoolean()))
2263 .thenReturn(mTestNotificationChannel);
2264
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002265 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002266 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002267 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002268 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002269 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2270 }
2271
2272 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002273 public void testDeleteChannelNotifyListener() throws Exception {
2274 List<String> associations = new ArrayList<>();
2275 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002276 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2277 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002278 mService.setPreferencesHelper(mPreferencesHelper);
2279 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002280 eq(mTestNotificationChannel.getId()), anyBoolean()))
2281 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002282 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002283 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002284 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002285 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002286 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2287 }
2288
2289 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002290 public void testDeleteChannelGroupNotifyListener() throws Exception {
2291 List<String> associations = new ArrayList<>();
2292 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002293 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2294 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002295 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002296 mService.setPreferencesHelper(mPreferencesHelper);
2297 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002298 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002299 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002300 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002301 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002302 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002303 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2304 }
2305
2306 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002307 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002308 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002309 List<String> associations = new ArrayList<>();
2310 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002311 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2312 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002313 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002314 eq(mTestNotificationChannel.getId()), anyBoolean()))
2315 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002316
2317 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002318 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002319
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002320 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002321 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002322
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002323 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002324 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002325 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2326 }
2327
2328 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002329 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002330 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002331 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002332 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2333 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002334
2335 try {
2336 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002337 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002338 fail("listeners that don't have a companion device shouldn't be able to call this");
2339 } catch (SecurityException e) {
2340 // pass
2341 }
2342
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002343 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002344 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002345
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002346 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002347 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2348 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2349 }
2350
2351 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002352 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002353 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002354 List<String> associations = new ArrayList<>();
2355 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002356 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2357 .thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002358 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002359 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002360 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002361 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002362
2363 try {
2364 mBinderService.updateNotificationChannelFromPrivilegedListener(
2365 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2366 fail("incorrectly allowed a change to a user listener cannot see");
2367 } catch (SecurityException e) {
2368 // pass
2369 }
2370
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002371 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002372 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002373
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002374 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002375 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002376 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2377 }
2378
2379 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002380 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002381 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002382 List<String> associations = new ArrayList<>();
2383 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002384 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2385 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002386
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002387 mBinderService.getNotificationChannelsFromPrivilegedListener(
2388 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002389
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002390 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002391 anyString(), anyInt(), anyBoolean());
2392 }
2393
2394 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002395 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002396 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002397 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002398 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2399 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002400
2401 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002402 mBinderService.getNotificationChannelsFromPrivilegedListener(
2403 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002404 fail("listeners that don't have a companion device shouldn't be able to call this");
2405 } catch (SecurityException e) {
2406 // pass
2407 }
2408
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002409 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002410 anyString(), anyInt(), anyBoolean());
2411 }
2412
2413 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002414 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2415 throws Exception {
2416 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldse61758a2020-06-10 10:26:44 -04002417 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2418 .thenReturn(new ArrayList<>());
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002419 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2420
2421 mBinderService.getNotificationChannelsFromPrivilegedListener(
2422 null, PKG, Process.myUserHandle());
2423
2424 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2425 anyString(), anyInt(), anyBoolean());
2426 }
2427
2428 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002429 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2430 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002431 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldse61758a2020-06-10 10:26:44 -04002432 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2433 .thenReturn(new ArrayList<>());
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002434 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2435
2436 try {
2437 mBinderService.getNotificationChannelsFromPrivilegedListener(
2438 null, PKG, Process.myUserHandle());
2439 fail("listeners that don't have a companion device shouldn't be able to call this");
2440 } catch (SecurityException e) {
2441 // pass
2442 }
2443
2444 verify(mPreferencesHelper, never()).getNotificationChannels(
2445 anyString(), anyInt(), anyBoolean());
2446 }
2447
2448 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002449 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002450 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002451 List<String> associations = new ArrayList<>();
2452 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002453 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2454 .thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002455 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2456 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002457 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002458
2459 try {
2460 mBinderService.getNotificationChannelsFromPrivilegedListener(
2461 null, PKG, Process.myUserHandle());
2462 fail("listener getting channels from a user they cannot see");
2463 } catch (SecurityException e) {
2464 // pass
2465 }
2466
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002467 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002468 anyString(), anyInt(), anyBoolean());
2469 }
2470
2471 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002472 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002473 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002474 List<String> associations = new ArrayList<>();
2475 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002476 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2477 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002478
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002479 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2480 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002481
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002482 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002483 }
2484
2485 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002486 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002487 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002488 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002489 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2490 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002491
2492 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002493 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2494 null, PKG, Process.myUserHandle());
2495 fail("listeners that don't have a companion device shouldn't be able to call this");
2496 } catch (SecurityException e) {
2497 // pass
2498 }
2499
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002500 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002501 }
2502
2503 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002504 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002505 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002506 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002507 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2508 .thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002509 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2510 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002511 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002512 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002513 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2514 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002515 fail("listeners that don't have a companion device shouldn't be able to call this");
2516 } catch (SecurityException e) {
2517 // pass
2518 }
2519
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002520 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002521 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002522
2523 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002524 public void testHasCompanionDevice_failure() throws Exception {
2525 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2526 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002527 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002528 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002529
2530 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002531 public void testHasCompanionDevice_noService() {
Will Brockmancfd98302020-01-29 15:57:30 -05002532 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
2533 mNotificationInstanceIdSequence);
Julia Reynolds727a7282017-04-13 10:54:01 -04002534
Julia Reynolds503ed942017-10-04 16:04:56 -04002535 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002536 }
2537
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002538 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002539 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2540 final NotificationRecord notification = generateNotificationRecord(
2541 mTestNotificationChannel, 1, null, true);
2542 mService.addNotification(notification);
2543 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2544
2545 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2546 mService.new SnoozeNotificationRunnable(
2547 notification.getKey(), 100, null);
2548 snoozeNotificationRunnable.run();
2549 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2550 mService.new SnoozeNotificationRunnable(
2551 notification.getKey(), 100, null);
2552 snoozeNotificationRunnable.run();
2553
2554 // snooze twice
2555 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2556 }
2557
2558 @Test
2559 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2560 final NotificationRecord notification = generateNotificationRecord(
2561 mTestNotificationChannel, 1, "group", true);
2562 mService.addNotification(notification);
2563 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2564
2565 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2566 mService.new SnoozeNotificationRunnable(
2567 notification.getKey(), 100, null);
2568 snoozeNotificationRunnable.run();
2569 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2570 mService.new SnoozeNotificationRunnable(
2571 notification.getKey(), 100, null);
2572 snoozeNotificationRunnable.run();
2573
2574 // snooze twice
2575 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2576 }
2577
2578 @Test
2579 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2580 final NotificationRecord notification = generateNotificationRecord(
2581 mTestNotificationChannel, 1, "group", true);
2582 final NotificationRecord notification2 = generateNotificationRecord(
2583 mTestNotificationChannel, 2, "group", true);
2584 mService.addNotification(notification);
2585 mService.addNotification(notification2);
2586 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2587 when(mSnoozeHelper.getNotifications(
2588 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2589
2590 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2591 mService.new SnoozeNotificationRunnable(
2592 notification.getKey(), 100, null);
2593 snoozeNotificationRunnable.run();
2594 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2595 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2596 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2597 mService.new SnoozeNotificationRunnable(
2598 notification.getKey(), 100, null);
2599 snoozeNotificationRunnable.run();
2600
2601 // snooze twice
2602 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2603 }
2604
2605 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002606 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2607 final NotificationRecord nonGrouped = generateNotificationRecord(
2608 mTestNotificationChannel, 1, null, false);
2609 final NotificationRecord grouped = generateNotificationRecord(
2610 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002611 mService.addNotification(grouped);
2612 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002613
2614 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002615 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002616 nonGrouped.getKey(), 100, null);
2617 snoozeNotificationRunnable.run();
2618
2619 // only snooze the one notification
2620 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002621 assertTrue(nonGrouped.getStats().hasSnoozed());
Will Brockman9918db92020-03-06 16:48:39 -05002622
2623 assertEquals(2, mNotificationRecordLogger.numCalls());
2624 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2625 mNotificationRecordLogger.event(0));
2626 assertEquals(
2627 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2628 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002629 }
2630
2631 @Test
2632 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2633 final NotificationRecord parent = generateNotificationRecord(
2634 mTestNotificationChannel, 1, "group", true);
2635 final NotificationRecord child = generateNotificationRecord(
2636 mTestNotificationChannel, 2, "group", false);
2637 final NotificationRecord child2 = generateNotificationRecord(
2638 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002639 mService.addNotification(parent);
2640 mService.addNotification(child);
2641 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002642
2643 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002644 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002645 parent.getKey(), 100, null);
2646 snoozeNotificationRunnable.run();
2647
2648 // snooze parent and children
2649 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2650 }
2651
2652 @Test
2653 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2654 final NotificationRecord parent = generateNotificationRecord(
2655 mTestNotificationChannel, 1, "group", true);
2656 final NotificationRecord child = generateNotificationRecord(
2657 mTestNotificationChannel, 2, "group", false);
2658 final NotificationRecord child2 = generateNotificationRecord(
2659 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002660 mService.addNotification(parent);
2661 mService.addNotification(child);
2662 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002663
2664 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002665 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002666 child2.getKey(), 100, null);
2667 snoozeNotificationRunnable.run();
2668
2669 // only snooze the one child
2670 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002671
2672 assertEquals(2, mNotificationRecordLogger.numCalls());
2673 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2674 mNotificationRecordLogger.event(0));
2675 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
2676 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002677 }
2678
2679 @Test
2680 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2681 final NotificationRecord parent = generateNotificationRecord(
2682 mTestNotificationChannel, 1, "group", true);
Julia Reynolds24edc002020-01-29 16:35:32 -05002683 assertTrue(parent.getSbn().getNotification().isGroupSummary());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002684 final NotificationRecord child = generateNotificationRecord(
2685 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002686 mService.addNotification(parent);
2687 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002688
2689 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002690 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002691 child.getKey(), 100, null);
2692 snoozeNotificationRunnable.run();
2693
2694 // snooze child and summary
2695 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002696
2697 assertEquals(4, mNotificationRecordLogger.numCalls());
2698 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2699 mNotificationRecordLogger.event(0));
2700 assertEquals(
2701 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2702 mNotificationRecordLogger.event(1));
2703 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2704 mNotificationRecordLogger.event(2));
2705 assertEquals(
2706 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2707 mNotificationRecordLogger.event(3));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002708 }
2709
2710 @Test
2711 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2712 final NotificationRecord child = generateNotificationRecord(
2713 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002714 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002715
2716 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002717 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002718 child.getKey(), 100, null);
2719 snoozeNotificationRunnable.run();
2720
2721 // snooze child only
2722 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002723
2724 assertEquals(2, mNotificationRecordLogger.numCalls());
2725 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2726 mNotificationRecordLogger.event(0));
2727 assertEquals(
2728 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2729 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002730 }
2731
2732 @Test
2733 public void testPostGroupChild_unsnoozeParent() throws Exception {
2734 final NotificationRecord child = generateNotificationRecord(
2735 mTestNotificationChannel, 2, "group", false);
2736
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002737 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002738 child.getSbn().getId(), child.getSbn().getNotification(),
2739 child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002740 waitForIdle();
2741
2742 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2743 anyString(), anyInt(), eq(child.getGroupKey()));
2744 }
2745
2746 @Test
2747 public void testPostNonGroup_noUnsnoozing() throws Exception {
2748 final NotificationRecord record = generateNotificationRecord(
2749 mTestNotificationChannel, 2, null, false);
2750
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002751 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002752 record.getSbn().getId(), record.getSbn().getNotification(),
2753 record.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002754 waitForIdle();
2755
2756 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2757 }
2758
2759 @Test
2760 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2761 final NotificationRecord parent = generateNotificationRecord(
2762 mTestNotificationChannel, 2, "group", true);
2763
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002764 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002765 parent.getSbn().getId(), parent.getSbn().getNotification(),
2766 parent.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002767 waitForIdle();
2768
2769 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2770 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002771
2772 @Test
Julia Reynolds0d073782020-02-13 16:07:52 -05002773 public void testSystemNotificationListenerCanUnsnooze() throws Exception {
2774 final NotificationRecord nr = generateNotificationRecord(
2775 mTestNotificationChannel, 2, "group", false);
2776
2777 mBinderService.enqueueNotificationWithTag(PKG, PKG,
2778 "testSystemNotificationListenerCanUnsnooze",
2779 nr.getSbn().getId(), nr.getSbn().getNotification(),
2780 nr.getSbn().getUserId());
2781 waitForIdle();
2782 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2783 mService.new SnoozeNotificationRunnable(
2784 nr.getKey(), 100, null);
2785 snoozeNotificationRunnable.run();
2786
2787 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
2788 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
2789 listener.isSystem = true;
2790 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
2791
2792 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
2793 waitForIdle();
2794 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
2795 assertEquals(1, notifs.length);
2796 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
2797 }
2798
2799 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002800 public void testSetListenerAccessForUser() throws Exception {
2801 UserHandle user = UserHandle.of(10);
2802 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002803 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2804
Julia Reynolds92febc32017-10-26 11:30:31 -04002805
2806 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2807 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2808 c.flattenToString(), user.getIdentifier(), true, true);
2809 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2810 c.flattenToString(), user.getIdentifier(), false, true);
2811 verify(mAssistants, never()).setPackageOrComponentEnabled(
2812 any(), anyInt(), anyBoolean(), anyBoolean());
2813 }
2814
2815 @Test
2816 public void testSetAssistantAccessForUser() throws Exception {
2817 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002818 List<UserInfo> uis = new ArrayList<>();
2819 UserInfo ui = new UserInfo();
2820 ui.id = 10;
2821 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002822 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002823 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2824
2825 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002826
2827 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2828 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2829 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002830 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002831 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2832 c.flattenToString(), user.getIdentifier(), false, true);
2833 verify(mListeners, never()).setPackageOrComponentEnabled(
2834 any(), anyInt(), anyBoolean(), anyBoolean());
2835 }
2836
2837 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002838 public void testGetAssistantAllowedForUser() throws Exception {
2839 UserHandle user = UserHandle.of(10);
2840 try {
2841 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2842 } catch (IllegalStateException e) {
2843 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2844 throw e;
2845 }
2846 }
2847 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2848 }
2849
2850 @Test
2851 public void testGetAssistantAllowed() throws Exception {
2852 try {
2853 mBinderService.getAllowedNotificationAssistant();
2854 } catch (IllegalStateException e) {
2855 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2856 throw e;
2857 }
2858 }
2859 verify(mAssistants, times(1)).getAllowedComponents(0);
2860 }
2861
2862 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002863 public void testSetDndAccessForUser() throws Exception {
2864 UserHandle user = UserHandle.of(10);
2865 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002866 mBinderService.setNotificationPolicyAccessGrantedForUser(
2867 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002868
2869 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2870 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2871 c.getPackageName(), user.getIdentifier(), true, true);
2872 verify(mAssistants, never()).setPackageOrComponentEnabled(
2873 any(), anyInt(), anyBoolean(), anyBoolean());
2874 verify(mListeners, never()).setPackageOrComponentEnabled(
2875 any(), anyInt(), anyBoolean(), anyBoolean());
2876 }
2877
2878 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002879 public void testSetListenerAccess() throws Exception {
2880 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002881 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002882
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002883 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002884 c.flattenToString(), 0, true, true);
2885 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2886 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002887 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002888 any(), anyInt(), anyBoolean(), anyBoolean());
2889 }
2890
2891 @Test
2892 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002893 List<UserInfo> uis = new ArrayList<>();
2894 UserInfo ui = new UserInfo();
2895 ui.id = 0;
2896 uis.add(ui);
2897 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002898 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002899
2900 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002901
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002902 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002903 c.flattenToString(), 0, true, true);
2904 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2905 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002906 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002907 any(), anyInt(), anyBoolean(), anyBoolean());
2908 }
2909
2910 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002911 public void testSetAssistantAccess_multiProfile() throws Exception {
2912 List<UserInfo> uis = new ArrayList<>();
2913 UserInfo ui = new UserInfo();
2914 ui.id = 0;
2915 uis.add(ui);
2916 UserInfo ui10 = new UserInfo();
2917 ui10.id = 10;
2918 uis.add(ui10);
2919 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2920 ComponentName c = ComponentName.unflattenFromString("package/Component");
2921
2922 mBinderService.setNotificationAssistantAccessGranted(c, true);
2923
2924 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2925 c.flattenToString(), 0, true, true);
2926 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2927 c.flattenToString(), 10, true, true);
2928 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2929 c.flattenToString(), 0, false, true);
2930 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2931 c.flattenToString(), 10, false, true);
2932 verify(mListeners, never()).setPackageOrComponentEnabled(
2933 any(), anyInt(), anyBoolean(), anyBoolean());
2934 }
2935
2936 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002937 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2938 ArrayList<ComponentName> componentList = new ArrayList<>();
2939 ComponentName c = ComponentName.unflattenFromString("package/Component");
2940 componentList.add(c);
2941 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002942 List<UserInfo> uis = new ArrayList<>();
2943 UserInfo ui = new UserInfo();
2944 ui.id = 0;
2945 uis.add(ui);
2946 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002947
Julia Reynolds4afe2642019-05-01 08:42:24 -04002948 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002949
2950 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2951 c.flattenToString(), 0, true, false);
2952 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2953 c.flattenToString(), 0, false, false);
2954 verify(mListeners, never()).setPackageOrComponentEnabled(
2955 any(), anyInt(), anyBoolean(), anyBoolean());
2956 }
2957
2958 @Test
2959 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002960 List<UserInfo> uis = new ArrayList<>();
2961 UserInfo ui = new UserInfo();
2962 ui.id = 10;
2963 uis.add(ui);
2964 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002965 ArrayList<ComponentName> componentList = new ArrayList<>();
2966 ComponentName c = ComponentName.unflattenFromString("package/Component");
2967 componentList.add(c);
2968 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002969 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002970
Julia Reynolds4afe2642019-05-01 08:42:24 -04002971 mBinderService.setNotificationAssistantAccessGrantedForUser(
2972 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002973
2974 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2975 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002976 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002977 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2978 c.flattenToString(), user.getIdentifier(), false, false);
2979 verify(mListeners, never()).setPackageOrComponentEnabled(
2980 any(), anyInt(), anyBoolean(), anyBoolean());
2981 }
2982
2983 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002984 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2985 throws Exception {
2986 List<UserInfo> uis = new ArrayList<>();
2987 UserInfo ui = new UserInfo();
2988 ui.id = 0;
2989 uis.add(ui);
2990 UserInfo ui10 = new UserInfo();
2991 ui10.id = 10;
2992 uis.add(ui10);
2993 UserHandle user = ui.getUserHandle();
2994 ArrayList<ComponentName> componentList = new ArrayList<>();
2995 ComponentName c = ComponentName.unflattenFromString("package/Component");
2996 componentList.add(c);
2997 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2998 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2999
3000 mBinderService.setNotificationAssistantAccessGrantedForUser(
3001 null, user.getIdentifier(), true);
3002
3003 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3004 c.flattenToString(), user.getIdentifier(), true, false);
3005 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3006 c.flattenToString(), ui10.id, true, false);
3007 verify(mAssistants).setUserSet(0, true);
3008 verify(mAssistants).setUserSet(10, true);
3009 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3010 c.flattenToString(), user.getIdentifier(), false, false);
3011 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3012 c.flattenToString(), ui10.id, false, false);
3013 verify(mListeners, never()).setPackageOrComponentEnabled(
3014 any(), anyInt(), anyBoolean(), anyBoolean());
3015 }
3016
3017 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04003018 public void testSetDndAccess() throws Exception {
3019 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003020
3021 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04003022
3023 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3024 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003025 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003026 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003027 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003028 any(), anyInt(), anyBoolean(), anyBoolean());
3029 }
Julia Reynolds68263d12017-06-21 14:21:19 -04003030
3031 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003032 public void testSetListenerAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003033 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3034 ComponentName c = ComponentName.unflattenFromString("package/Component");
3035 mBinderService.setNotificationListenerAccessGranted(c, true);
3036
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003037 verify(mListeners).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003038 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003039 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003040 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003041 verify(mAssistants).migrateToXml();
3042 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04003043 }
3044
3045 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003046 public void testSetAssistantAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003047 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3048 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003049 List<UserInfo> uis = new ArrayList<>();
3050 UserInfo ui = new UserInfo();
3051 ui.id = 0;
3052 uis.add(ui);
3053 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3054
Julia Reynolds68263d12017-06-21 14:21:19 -04003055 mBinderService.setNotificationAssistantAccessGranted(c, true);
3056
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003057 verify(mListeners).migrateToXml();
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003058 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003059 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003060 verify(mAssistants).migrateToXml();
3061 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04003062 }
3063
3064 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003065 public void testSetDndAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003066 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3067 ComponentName c = ComponentName.unflattenFromString("package/Component");
3068 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3069
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003070 verify(mListeners).migrateToXml();
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003071 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003072 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003073 verify(mAssistants).migrateToXml();
3074 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynoldse1816412017-10-24 10:39:11 -04003075 }
3076
3077 @Test
3078 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3079 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3080 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3081 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003082
3083 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003084
3085 verify(mListeners, times(1)).setPackageOrComponentEnabled(
3086 c.flattenToString(), 0, true, true);
3087 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003088 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003089 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003090 any(), anyInt(), anyBoolean(), anyBoolean());
3091 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04003092
3093 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04003094 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3095 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3096 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3097 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003098 List<UserInfo> uis = new ArrayList<>();
3099 UserInfo ui = new UserInfo();
3100 ui.id = 0;
3101 uis.add(ui);
3102 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3103
3104 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003105
3106 verify(mListeners, never()).setPackageOrComponentEnabled(
3107 anyString(), anyInt(), anyBoolean(), anyBoolean());
3108 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3109 c.flattenToString(), 0, false, true);
3110 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3111 c.flattenToString(), 0, true, true);
3112 }
3113
3114 @Test
3115 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3116 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3117 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3118 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003119
3120 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003121
3122 verify(mListeners, never()).setPackageOrComponentEnabled(
3123 anyString(), anyInt(), anyBoolean(), anyBoolean());
3124 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3125 c.getPackageName(), 0, true, true);
3126 verify(mAssistants, never()).setPackageOrComponentEnabled(
3127 any(), anyInt(), anyBoolean(), anyBoolean());
3128 }
3129
3130 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04003131 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
3132 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003133 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003134 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003135 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003136 runnable.run();
3137 waitForIdle();
3138
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003139 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003140 }
3141
3142 @Test
3143 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
3144 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003145 NotificationRecord r =
3146 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003147 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003148
3149 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003150 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003151 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003152 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003153 runnable.run();
3154 waitForIdle();
3155
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003156 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003157 }
3158
3159 @Test
3160 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
3161 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04003162 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
3163 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003164 mService.addNotification(r);
3165 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003166
3167 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003168 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003169 runnable.run();
3170 waitForIdle();
3171
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003172 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003173 }
Beverly40239d92017-07-07 10:20:41 -04003174
Julia Reynolds4db59552017-06-30 13:34:01 -04003175 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07003176 public void testDontAutogroupIfCritical() throws Exception {
3177 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3178 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
3179 mService.addEnqueuedNotification(r);
3180 NotificationManagerService.PostNotificationRunnable runnable =
3181 mService.new PostNotificationRunnable(r.getKey());
3182 runnable.run();
3183
3184 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
3185 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
3186 runnable = mService.new PostNotificationRunnable(r.getKey());
3187 mService.addEnqueuedNotification(r);
3188
3189 runnable.run();
3190 waitForIdle();
3191
3192 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
3193 }
3194
3195 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04003196 public void testNoFakeColorizedPermission() throws Exception {
3197 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
3198 Notification.Builder nb = new Notification.Builder(mContext,
3199 mTestNotificationChannel.getId())
3200 .setContentTitle("foo")
3201 .setColorized(true)
3202 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
3203 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003204 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
3205 "testNoFakeColorizedPermission", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04003206 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04003207 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3208
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003209 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds24edc002020-01-29 16:35:32 -05003210 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003211 waitForIdle();
3212
Julia Reynolds503ed942017-10-04 16:04:56 -04003213 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003214 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003215
3216 assertFalse(posted.getNotification().isColorized());
3217 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003218
3219 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003220 public void testGetNotificationCountLocked() {
3221 String sampleTagToExclude = null;
3222 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003223 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003224 NotificationRecord r =
3225 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003226 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003227
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003228 }
3229 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003230 NotificationRecord r =
3231 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003232 mService.addNotification(r);
Julia Reynolds24edc002020-01-29 16:35:32 -05003233 sampleTagToExclude = r.getSbn().getTag();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003234 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003235 }
3236
3237 // another package
3238 Notification n =
3239 new Notification.Builder(mContext, mTestNotificationChannel.getId())
3240 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3241 .build();
3242
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003243 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04003244 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003245 NotificationRecord otherPackage =
3246 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003247 mService.addEnqueuedNotification(otherPackage);
3248 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003249
3250 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003251 // anything that's currently enqueued or posted
Julia Reynoldse61758a2020-06-10 10:26:44 -04003252 int userId = UserHandle.getUserId(mUid);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003253 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003254 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003255 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003256 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003257
3258 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003259 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04003260 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003261
3262 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003263 assertEquals(39, mService.getNotificationCountLocked(
3264 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003265 }
3266
3267 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04003268 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003269 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003270 mService.addNotification(r);
3271 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003272
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003273 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003274 }
3275
3276 @Test
3277 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003278 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3279 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003280 mService.addNotification(r);
3281 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003282
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003283 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003284 }
3285
3286 @Test
3287 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003288 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3289 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003290 mService.addNotification(r);
3291 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003292
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003293 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003294 }
3295
3296 @Test
3297 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04003298 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003299 NotificationManagerService.WorkerHandler handler = mock(
3300 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003301 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003302
3303 Map<String, Answer> answers = getSignalExtractorSideEffects();
3304 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04003305 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003306 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003307 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003308
3309 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
3310
Julia Reynolds503ed942017-10-04 16:04:56 -04003311 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003312 }
3313 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
3314 }
3315
3316 @Test
3317 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003318 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003319 NotificationManagerService.WorkerHandler handler = mock(
3320 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003321 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003322
3323 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003324 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003325
Julia Reynolds503ed942017-10-04 16:04:56 -04003326 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003327 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003328 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003329
3330 @Test
3331 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04003332 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003333 + "<ranking></ranking>"
3334 + "<enabled_listeners>"
3335 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3336 + "</enabled_listeners>"
3337 + "<enabled_assistants>"
3338 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3339 + "</enabled_assistants>"
3340 + "<dnd_apps>"
3341 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3342 + "</dnd_apps>"
3343 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003344 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003345 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3346 false,
3347 UserHandle.USER_ALL);
3348 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3349 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3350 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003351
3352 // numbers are inflated for setup
3353 verify(mListeners, times(1)).migrateToXml();
3354 verify(mConditionProviders, times(1)).migrateToXml();
3355 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003356 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003357 }
3358
3359 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003360 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
3361 final String upgradeXml = "<notification-policy version=\"1\">"
3362 + "<snoozed-notifications>></snoozed-notifications>"
3363 + "</notification-policy>";
3364 mService.readPolicyXml(
3365 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3366 false,
3367 UserHandle.USER_ALL);
Julia Reynolds9050d9a2020-02-20 09:38:05 -05003368 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong());
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003369 }
3370
3371 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003372 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
3373 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003374 + "<ranking></ranking>"
3375 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003376 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003377 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
3378 false,
3379 UserHandle.USER_ALL);
3380 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
3381 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
3382 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003383
3384 // numbers are inflated for setup
3385 verify(mListeners, times(2)).migrateToXml();
3386 verify(mConditionProviders, times(2)).migrateToXml();
3387 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003388 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003389 }
3390
Annie Meng8b646fd2019-02-01 18:46:42 +00003391 @Test
3392 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3393 final String policyXml = "<notification-policy version=\"1\">"
3394 + "<ranking></ranking>"
3395 + "<enabled_listeners>"
3396 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3397 + "</enabled_listeners>"
3398 + "<enabled_assistants>"
3399 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3400 + "</enabled_assistants>"
3401 + "<dnd_apps>"
3402 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3403 + "</dnd_apps>"
3404 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003405 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00003406 mService.readPolicyXml(
3407 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3408 true,
3409 10);
3410 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3411 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3412 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3413 }
3414
3415 @Test
3416 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3417 final String policyXml = "<notification-policy version=\"1\">"
3418 + "<ranking></ranking>"
3419 + "<enabled_listeners>"
3420 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3421 + "</enabled_listeners>"
3422 + "<enabled_assistants>"
3423 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3424 + "</enabled_assistants>"
3425 + "<dnd_apps>"
3426 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3427 + "</dnd_apps>"
3428 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003429 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003430 mService.readPolicyXml(
3431 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3432 true,
3433 10);
3434 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3435 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3436 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3437 }
Beverlyd4f96492017-08-02 13:36:11 -04003438
3439 @Test
3440 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3441 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003442 mService.mZenModeHelper = mZenModeHelper;
3443 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003444 new Intent(Intent.ACTION_LOCALE_CHANGED));
3445
3446 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3447 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003448
3449 @Test
3450 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003451 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003452 final ApplicationInfo legacy = new ApplicationInfo();
3453 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3454 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3455 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003456 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3457 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003458 getContext().setMockPackageManager(mPackageManagerClient);
3459
3460 Notification.Builder nb = new Notification.Builder(mContext,
3461 NotificationChannel.DEFAULT_CHANNEL_ID)
3462 .setContentTitle("foo")
3463 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003464 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003465 .setPriority(Notification.PRIORITY_MIN);
3466
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003467 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3468 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynoldse61758a2020-06-10 10:26:44 -04003469 Binder.getCallingUid(), 0, nb.build(),
3470 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003471
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003472 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3473 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003474 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003475
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003476 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003477 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003478
3479 nb = new Notification.Builder(mContext)
3480 .setContentTitle("foo")
3481 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003482 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003483 .setPriority(Notification.PRIORITY_MIN);
3484
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003485 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3486 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04003487 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003488
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003489 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3490 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003491 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3492 waitForIdle();
3493 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003494 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003495
3496 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003497 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003498 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3499 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003500
3501 @Test
3502 public void testStats_updatedOnDirectReply() throws Exception {
3503 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3504 mService.addNotification(r);
3505
3506 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3507 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Julia Reynolds24edc002020-01-29 16:35:32 -05003508 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.getSbn()));
Will Brockman9918db92020-03-06 16:48:39 -05003509
3510 assertEquals(1, mNotificationRecordLogger.numCalls());
3511 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
3512 mNotificationRecordLogger.event(0));
Julia Reynolds503ed942017-10-04 16:04:56 -04003513 }
3514
3515 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003516 public void testStats_updatedOnUserExpansion() throws Exception {
3517 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003518 mService.addNotification(r);
3519
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003520 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3521 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003522 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3523 eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003524 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003525
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003526 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3527 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003528 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3529 eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003530 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Will Brockman9918db92020-03-06 16:48:39 -05003531
3532 assertEquals(2, mNotificationRecordLogger.numCalls());
3533 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
3534 mNotificationRecordLogger.event(0));
3535 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
3536 mNotificationRecordLogger.event(1));
Julia Reynolds503ed942017-10-04 16:04:56 -04003537 }
3538
3539 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003540 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3541 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3542 mService.addNotification(r);
3543
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003544 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3545 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003546 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Julia Reynolds24edc002020-01-29 16:35:32 -05003547 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(false),
3548 eq((true)));
Tony Makeda84a72018-11-19 17:01:32 +00003549
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003550 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3551 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003552 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003553 verify(mAssistants).notifyAssistantExpansionChangedLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003554 eq(r.getSbn()), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003555 }
3556
3557 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003558 public void testStats_updatedOnViewSettings() throws Exception {
3559 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3560 mService.addNotification(r);
3561
3562 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3563 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3564 }
3565
3566 @Test
3567 public void testStats_updatedOnVisibilityChanged() throws Exception {
3568 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3569 mService.addNotification(r);
3570
Dieter Hsud39f0d52018-04-14 02:08:30 +08003571 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003572 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3573 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
Julia Reynolds24edc002020-01-29 16:35:32 -05003574 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(true));
Julia Reynolds503ed942017-10-04 16:04:56 -04003575 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3576 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3577 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
Julia Reynolds24edc002020-01-29 16:35:32 -05003578 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(false));
Julia Reynolds503ed942017-10-04 16:04:56 -04003579 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3580 }
3581
3582 @Test
3583 public void testStats_dismissalSurface() throws Exception {
3584 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Will Brockman4f0f9d22020-02-23 21:18:11 -05003585 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003586 mService.addNotification(r);
3587
Dieter Hsud39f0d52018-04-14 02:08:30 +08003588 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003589 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3590 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003591 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003592 waitForIdle();
3593
3594 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
Will Brockman75c60572020-01-31 10:30:27 -05003595
3596 // Using mService.addNotification() does not generate a NotificationRecordLogger log,
3597 // so we only get the cancel notification.
Will Brockman9918db92020-03-06 16:48:39 -05003598 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockman75c60572020-01-31 10:30:27 -05003599
Will Brockman75c60572020-01-31 10:30:27 -05003600 assertEquals(
3601 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
Will Brockman9918db92020-03-06 16:48:39 -05003602 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05003603 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003604 }
3605
3606 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003607 public void testStats_dismissalSentiment() throws Exception {
3608 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3609 mService.addNotification(r);
3610
3611 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003612 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3613 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003614 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3615 waitForIdle();
3616
3617 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3618 r.getStats().getDismissalSentiment());
3619 }
3620
3621 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003622 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003623 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3624 mService.addNotification(r);
3625 NotificationManagerService.WorkerHandler handler = mock(
3626 NotificationManagerService.WorkerHandler.class);
3627 mService.setHandler(handler);
3628
Julia Reynolds70aaea72018-07-13 13:38:34 -04003629 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3630
Julia Reynolds503ed942017-10-04 16:04:56 -04003631 Bundle signals = new Bundle();
3632 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003633 USER_SENTIMENT_NEGATIVE);
3634 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003635 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003636 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3637
3638 waitForIdle();
3639
3640 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3641 }
3642
3643 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003644 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003645 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3646 mService.addNotification(r);
3647 NotificationManagerService.WorkerHandler handler = mock(
3648 NotificationManagerService.WorkerHandler.class);
3649 mService.setHandler(handler);
3650
3651 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003652 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003653 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003654 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003655 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3656 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3657
3658 waitForIdle();
3659
3660 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3661 verify(handler, times(1)).scheduleCancelNotification(any());
3662 }
3663
3664 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003665 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3666 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3667 mService.addEnqueuedNotification(r);
3668 NotificationManagerService.WorkerHandler handler = mock(
3669 NotificationManagerService.WorkerHandler.class);
3670 mService.setHandler(handler);
3671 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3672
3673 Bundle signals = new Bundle();
3674 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3675 USER_SENTIMENT_NEGATIVE);
3676 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003677 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003678 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3679
3680 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3681 }
3682
3683 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003684 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003685 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3686 mService.addEnqueuedNotification(r);
3687 NotificationManagerService.WorkerHandler handler = mock(
3688 NotificationManagerService.WorkerHandler.class);
3689 mService.setHandler(handler);
3690 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3691
3692 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003693 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003694 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003695 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05003696 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3697
3698 assertEquals(IMPORTANCE_LOW, r.getImportance());
3699 }
3700
3701 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003702 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3703 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3704 mService.addEnqueuedNotification(r);
3705 NotificationManagerService.WorkerHandler handler = mock(
3706 NotificationManagerService.WorkerHandler.class);
3707 mService.setHandler(handler);
3708 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3709
3710 Bundle signals = new Bundle();
3711 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3712 USER_SENTIMENT_NEGATIVE);
3713 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003714 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003715 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3716
3717 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3718
3719 waitForIdle();
3720
3721 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3722 }
3723
3724 @Test
3725 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3726 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3727 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003728 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3729
3730 Bundle signals = new Bundle();
3731 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3732 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003733 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003734 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds503ed942017-10-04 16:04:56 -04003735 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3736
3737 waitForIdle();
3738
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003739 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003740 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003741
3742 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003743 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3744 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3745 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003746 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003747
3748 Bundle signals = new Bundle();
3749 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003750 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003751 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003752 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003753 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3754
3755 waitForIdle();
3756
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003757 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003758 }
3759
3760 @Test
3761 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3762 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3763 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003764 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003765
3766 Bundle signals = new Bundle();
3767 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003768 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003769 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003770 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003771 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3772
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003773 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003774 }
3775
3776 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003777 public void testRestore() throws Exception {
3778 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003779 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003780 assertEquals(1, mService.countSystemChecks - systemChecks);
3781 }
3782
3783 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003784 public void testBackupEmptySound() throws Exception {
3785 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3786 channel.setSound(Uri.EMPTY, null);
3787
3788 XmlSerializer serializer = new FastXmlSerializer();
3789 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3790 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3791 channel.writeXmlForBackup(serializer, getContext());
3792
3793 XmlPullParser parser = Xml.newPullParser();
3794 parser.setInput(new BufferedInputStream(
3795 new ByteArrayInputStream(baos.toByteArray())), null);
3796 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3797 restored.populateFromXmlForRestore(parser, getContext());
3798
3799 assertNull(restored.getSound());
3800 }
3801
3802 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003803 public void testBackup() throws Exception {
3804 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04003805 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3806 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003807 mBinderService.getBackupPayload(1);
3808 assertEquals(1, mService.countSystemChecks - systemChecks);
3809 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003810
3811 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003812 public void testEmptyVibration_noException() throws Exception {
3813 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3814 channel.setVibrationPattern(new long[0]);
3815
3816 XmlSerializer serializer = new FastXmlSerializer();
3817 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3818 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3819 channel.writeXml(serializer);
3820 }
3821
3822 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003823 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003824 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003825 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003826 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3827 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003828 message1.setData("",
3829 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003830 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003831 message2.setData("",
3832 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003833
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003834 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003835 .setContentTitle("foo")
3836 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3837 .setStyle(new Notification.MessagingStyle("")
3838 .addMessage(message1)
3839 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003840 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
Julia Reynoldse61758a2020-06-10 10:26:44 -04003841 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
3842 null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003843
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003844 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003845 reset(mUgm);
3846 reset(mUgmInternal);
3847 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003848 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003849 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003850 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003851 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003852 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003853 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3854
3855 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003856 .setContentTitle("foo")
3857 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3858 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003859 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
Julia Reynoldse61758a2020-06-10 10:26:44 -04003860 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
3861 c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003862
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003863 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003864 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003865 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003866 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003867 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3868 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003869
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003870 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003871 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003872 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003873 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003874 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003875 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003876
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003877 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003878 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003879 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003880 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003881 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003882 anyInt(), anyInt());
3883 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003884
3885 @Test
Julia Reynoldsea58c202020-02-03 12:52:49 -05003886 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
3887 NotificationChannel c = new NotificationChannel(
3888 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
3889 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3890 Message message1 = new Message("", 0, "");
3891 message1.setData("",
3892 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
3893
3894 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
3895 .setContentTitle("foo")
3896 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3897 .setStyle(new Notification.MessagingStyle("")
3898 .addMessage(message1));
3899 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
Julia Reynoldse61758a2020-06-10 10:26:44 -04003900 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
3901 null, 0), c);
Julia Reynoldsea58c202020-02-03 12:52:49 -05003902
3903 doThrow(new SecurityException("no access")).when(mUgm)
3904 .grantUriPermissionFromOwner(
3905 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
3906
3907 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
3908 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM);
3909
3910 // yay, no crash
3911 }
3912
3913 @Test
Robin Leed107af62018-04-27 13:55:56 +02003914 public void testVisitUris() throws Exception {
3915 final Uri audioContents = Uri.parse("content://com.example/audio");
3916 final Uri backgroundImage = Uri.parse("content://com.example/background");
3917
3918 Bundle extras = new Bundle();
3919 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3920 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3921
3922 Notification n = new Notification.Builder(mContext, "a")
3923 .setContentTitle("notification with uris")
3924 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3925 .addExtras(extras)
3926 .build();
3927
3928 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3929 n.visitUris(visitor);
3930 verify(visitor, times(1)).accept(eq(audioContents));
3931 verify(visitor, times(1)).accept(eq(backgroundImage));
3932 }
3933
3934 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003935 public void testSetNotificationPolicy_preP_setOldFields() {
3936 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3937 mService.mZenModeHelper = mZenModeHelper;
3938 NotificationManager.Policy userPolicy =
3939 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3940 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3941
3942 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3943 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3944
3945 int expected = SUPPRESSED_EFFECT_BADGE
3946 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003947 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3948 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003949 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3950
3951 assertEquals(expected, actual);
3952 }
3953
3954 @Test
3955 public void testSetNotificationPolicy_preP_setNewFields() {
3956 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3957 mService.mZenModeHelper = mZenModeHelper;
3958 NotificationManager.Policy userPolicy =
3959 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3960 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3961
3962 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3963 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3964
3965 int expected = SUPPRESSED_EFFECT_BADGE;
3966 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3967
3968 assertEquals(expected, actual);
3969 }
3970
3971 @Test
3972 public void testSetNotificationPolicy_preP_setOldNewFields() {
3973 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3974 mService.mZenModeHelper = mZenModeHelper;
3975 NotificationManager.Policy userPolicy =
3976 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3977 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3978
3979 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3980 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3981
3982 int expected =
3983 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3984 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3985
3986 assertEquals(expected, actual);
3987 }
3988
3989 @Test
3990 public void testSetNotificationPolicy_P_setOldFields() {
3991 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3992 mService.mZenModeHelper = mZenModeHelper;
3993 NotificationManager.Policy userPolicy =
3994 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3995 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3996
3997 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3998 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3999
4000 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
4001 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
4002 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4003 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4004
4005 assertEquals(expected, actual);
4006 }
4007
4008 @Test
4009 public void testSetNotificationPolicy_P_setNewFields() {
4010 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4011 mService.mZenModeHelper = mZenModeHelper;
4012 NotificationManager.Policy userPolicy =
4013 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4014 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4015
4016 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4017 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
4018 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4019
4020 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
4021 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
4022 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4023 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4024
4025 assertEquals(expected, actual);
4026 }
4027
4028 @Test
4029 public void testSetNotificationPolicy_P_setOldNewFields() {
4030 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4031 mService.mZenModeHelper = mZenModeHelper;
4032 NotificationManager.Policy userPolicy =
4033 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4034 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4035
4036 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4037 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
4038
4039 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
4040 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4041
4042 assertEquals(expected, actual);
4043
4044 appPolicy = new NotificationManager.Policy(0, 0, 0,
4045 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
4046 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4047
4048 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
4049 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4050 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4051
4052 assertEquals(expected, actual);
4053 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05004054
4055 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04004056 public void testVisualDifference_foreground() {
4057 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4058 .setContentTitle("foo");
4059 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004060 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04004061 NotificationRecord r1 =
4062 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4063
4064 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4065 .setFlag(FLAG_FOREGROUND_SERVICE, true)
4066 .setContentTitle("bar");
4067 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004068 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04004069 NotificationRecord r2 =
4070 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4071
4072 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4073 }
4074
4075 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004076 public void testVisualDifference_diffTitle() {
4077 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4078 .setContentTitle("foo");
4079 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004080 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004081 NotificationRecord r1 =
4082 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4083
4084 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4085 .setContentTitle("bar");
4086 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004087 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004088 NotificationRecord r2 =
4089 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4090
4091 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4092 }
4093
4094 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004095 public void testVisualDifference_inboxStyle() {
4096 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4097 .setStyle(new Notification.InboxStyle()
4098 .addLine("line1").addLine("line2"));
4099 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004100 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004101 NotificationRecord r1 =
4102 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4103
4104 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4105 .setStyle(new Notification.InboxStyle()
4106 .addLine("line1").addLine("line2_changed"));
4107 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004108 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004109 NotificationRecord r2 =
4110 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4111
4112 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
4113
4114 Notification.Builder nb3 = new Notification.Builder(mContext, "")
4115 .setStyle(new Notification.InboxStyle()
4116 .addLine("line1"));
4117 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004118 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004119 NotificationRecord r3 =
4120 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
4121
4122 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
4123
4124 Notification.Builder nb4 = new Notification.Builder(mContext, "")
4125 .setStyle(new Notification.InboxStyle()
4126 .addLine("line1").addLine("line2").addLine("line3"));
4127 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004128 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004129 NotificationRecord r4 =
4130 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
4131
4132 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
4133
4134 Notification.Builder nb5 = new Notification.Builder(mContext, "")
4135 .setContentText("not an inbox");
4136 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004137 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004138 NotificationRecord r5 =
4139 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
4140
4141 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
4142 }
4143
4144 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004145 public void testVisualDifference_diffText() {
4146 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4147 .setContentText("foo");
4148 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004149 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004150 NotificationRecord r1 =
4151 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4152
4153 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4154 .setContentText("bar");
4155 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004156 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004157 NotificationRecord r2 =
4158 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4159
4160 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4161 }
4162
4163 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004164 public void testVisualDifference_sameText() {
4165 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4166 .setContentText("foo");
4167 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004168 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004169 NotificationRecord r1 =
4170 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4171
4172 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4173 .setContentText("foo");
4174 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004175 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004176 NotificationRecord r2 =
4177 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4178
4179 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4180 }
4181
4182 @Test
4183 public void testVisualDifference_sameTextButStyled() {
4184 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4185 .setContentText(Html.fromHtml("<b>foo</b>"));
4186 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004187 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004188 NotificationRecord r1 =
4189 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4190
4191 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4192 .setContentText(Html.fromHtml("<b>foo</b>"));
4193 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004194 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004195 NotificationRecord r2 =
4196 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4197
4198 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4199 }
4200
4201 @Test
4202 public void testVisualDifference_diffTextButStyled() {
4203 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4204 .setContentText(Html.fromHtml("<b>foo</b>"));
4205 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004206 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004207 NotificationRecord r1 =
4208 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4209
4210 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4211 .setContentText(Html.fromHtml("<b>bar</b>"));
4212 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004213 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004214 NotificationRecord r2 =
4215 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4216
4217 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4218 }
4219
4220 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004221 public void testVisualDifference_diffProgress() {
4222 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4223 .setProgress(100, 90, false);
4224 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004225 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004226 NotificationRecord r1 =
4227 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4228
4229 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4230 .setProgress(100, 100, false);
4231 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004232 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004233 NotificationRecord r2 =
4234 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4235
4236 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4237 }
4238
4239 @Test
4240 public void testVisualDifference_diffProgressNotDone() {
4241 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4242 .setProgress(100, 90, false);
4243 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004244 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004245 NotificationRecord r1 =
4246 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4247
4248 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4249 .setProgress(100, 91, false);
4250 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004251 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004252 NotificationRecord r2 =
4253 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4254
4255 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4256 }
Beverly5a20a5e2018-03-06 15:02:44 -05004257
4258 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004259 public void testVisualDifference_sameProgressStillDone() {
4260 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4261 .setProgress(100, 100, false);
4262 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004263 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004264 NotificationRecord r1 =
4265 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4266
4267 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4268 .setProgress(100, 100, false);
4269 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004270 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004271 NotificationRecord r2 =
4272 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4273
4274 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4275 }
4276
4277 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004278 public void testVisualDifference_summary() {
4279 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4280 .setGroup("bananas")
4281 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4282 .setContentText("foo");
4283 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004284 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004285 NotificationRecord r1 =
4286 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4287
4288 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4289 .setGroup("bananas")
4290 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4291 .setContentText("bar");
4292 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004293 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004294 NotificationRecord r2 =
4295 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4296
4297 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4298 }
4299
4300 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04004301 public void testVisualDifference_summaryNewNotification() {
4302 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4303 .setGroup("bananas")
4304 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4305 .setContentText("bar");
4306 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004307 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds760fa762018-06-19 15:39:23 -04004308 NotificationRecord r2 =
4309 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4310
4311 assertFalse(mService.isVisuallyInterruptive(null, r2));
4312 }
4313
4314 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05004315 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
4316 // post 2 notification from this package
4317 final NotificationRecord notif1 = generateNotificationRecord(
4318 mTestNotificationChannel, 1, null, true);
4319 final NotificationRecord notif2 = generateNotificationRecord(
4320 mTestNotificationChannel, 2, null, false);
4321 mService.addNotification(notif1);
4322 mService.addNotification(notif2);
4323
4324 // on broadcast, hide the 2 notifications
4325 mService.simulatePackageSuspendBroadcast(true, PKG);
4326 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
4327 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4328 assertEquals(2, captorHide.getValue().size());
4329
4330 // on broadcast, unhide the 2 notifications
4331 mService.simulatePackageSuspendBroadcast(false, PKG);
4332 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
4333 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4334 assertEquals(2, captorUnhide.getValue().size());
4335 }
4336
4337 @Test
4338 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
4339 // post 2 notification from this package
4340 final NotificationRecord notif1 = generateNotificationRecord(
4341 mTestNotificationChannel, 1, null, true);
4342 final NotificationRecord notif2 = generateNotificationRecord(
4343 mTestNotificationChannel, 2, null, false);
4344 mService.addNotification(notif1);
4345 mService.addNotification(notif2);
4346
4347 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4348 mService.simulatePackageSuspendBroadcast(true, "test_package");
4349 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4350 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4351 assertEquals(0, captor.getValue().size());
4352 }
Kristian Monsen05f34792018-04-09 10:27:16 +02004353
4354 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004355 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
4356 // Post 2 notifications from 2 packages
4357 NotificationRecord pkgA = new NotificationRecord(mContext,
4358 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4359 mService.addNotification(pkgA);
4360 NotificationRecord pkgB = new NotificationRecord(mContext,
4361 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4362 mService.addNotification(pkgB);
4363
4364 // on broadcast, hide one of the packages
4365 mService.simulatePackageDistractionBroadcast(
4366 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
4367 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4368 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4369 assertEquals(1, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004370 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004371
4372 // on broadcast, unhide the package
4373 mService.simulatePackageDistractionBroadcast(
4374 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
4375 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4376 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4377 assertEquals(1, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004378 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004379 }
4380
4381 @Test
4382 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
4383 // Post 2 notifications from 2 packages
4384 NotificationRecord pkgA = new NotificationRecord(mContext,
4385 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4386 mService.addNotification(pkgA);
4387 NotificationRecord pkgB = new NotificationRecord(mContext,
4388 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4389 mService.addNotification(pkgB);
4390
4391 // on broadcast, hide one of the packages
4392 mService.simulatePackageDistractionBroadcast(
4393 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
4394 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004395
4396 // should be called only once.
4397 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004398 assertEquals(2, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004399 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
4400 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004401
4402 // on broadcast, unhide the package
4403 mService.simulatePackageDistractionBroadcast(
4404 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
4405 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004406
4407 // should be called only once.
4408 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004409 assertEquals(2, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004410 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
4411 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004412 }
4413
4414 @Test
4415 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
4416 // post notification from this package
4417 final NotificationRecord notif1 = generateNotificationRecord(
4418 mTestNotificationChannel, 1, null, true);
4419 mService.addNotification(notif1);
4420
4421 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4422 mService.simulatePackageDistractionBroadcast(
4423 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
4424 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4425 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4426 assertEquals(0, captor.getValue().size());
4427 }
4428
4429 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004430 public void testCanUseManagedServicesNullPkg() {
4431 assertEquals(true, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004432 }
4433
Kristian Monsen05f34792018-04-09 10:27:16 +02004434
4435 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004436 public void testCanUseManagedServicesNoValidPkg() {
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004437 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4438 }
4439
4440 @Test
4441 public void testCanUseManagedServices_hasPermission() throws Exception {
4442 when(mPackageManager.checkPermission("perm", "pkg", 0))
4443 .thenReturn(PackageManager.PERMISSION_GRANTED);
4444
4445 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4446 }
4447
4448 @Test
4449 public void testCanUseManagedServices_noPermission() throws Exception {
4450 when(mPackageManager.checkPermission("perm", "pkg", 0))
4451 .thenReturn(PackageManager.PERMISSION_DENIED);
4452
4453 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4454 }
4455
4456 @Test
4457 public void testCanUseManagedServices_permDoesNotMatter() {
4458 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004459 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004460
4461 @Test
4462 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4463 final NotificationRecord r = generateNotificationRecord(
4464 mTestNotificationChannel, 1, null, true);
4465 r.setTextChanged(true);
4466 mService.addNotification(r);
4467
4468 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4469 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4470 new NotificationVisibility[]{});
4471
4472 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4473 }
4474
4475 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05004476 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
4477 final NotificationRecord r = generateNotificationRecord(
4478 mTestNotificationChannel, 1, null, true);
4479 r.setTextChanged(true);
Will Brockman4f0f9d22020-02-23 21:18:11 -05004480 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004481 mService.addNotification(r);
4482
4483 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4484 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4485 new NotificationVisibility[]{});
4486
Will Brockman9918db92020-03-06 16:48:39 -05004487 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004488 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
Will Brockman9918db92020-03-06 16:48:39 -05004489 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004490 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004491
4492 mService.mNotificationDelegate.onNotificationVisibilityChanged(
4493 new NotificationVisibility[]{},
4494 new NotificationVisibility[]
4495 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
4496 );
4497
Will Brockman9918db92020-03-06 16:48:39 -05004498 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004499 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
Will Brockman9918db92020-03-06 16:48:39 -05004500 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004501 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004502 }
4503
4504 @Test
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004505 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4506 throws RemoteException {
4507 final NotificationRecord r = generateNotificationRecord(
4508 mTestNotificationChannel, 1, null, true);
4509 r.setTextChanged(true);
4510 mService.addNotification(r);
4511
4512 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4513
4514 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4515 }
4516
4517 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004518 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004519 throws RemoteException {
4520 final NotificationRecord r = generateNotificationRecord(
4521 mTestNotificationChannel, 1, null, true);
4522 r.setInterruptive(true);
4523 mService.addNotification(r);
4524
4525 mService.maybeRecordInterruptionLocked(r);
4526 mService.maybeRecordInterruptionLocked(r);
4527
4528 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4529 anyString(), anyString(), anyInt());
Julia Reynoldsfd9f8342020-03-06 09:36:00 -05004530 verify(mHistoryManager, times(1)).addNotification(any());
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004531 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004532
4533 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004534 public void testBubble() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004535 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4536 assertFalse(mBinderService.areBubblesAllowed(PKG));
4537 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4538 BUBBLE_PREFERENCE_NONE);
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004539 }
4540
4541 @Test
Mady Mellora92268c2020-03-09 17:25:08 -07004542 public void testUserApprovedBubblesForPackageSelected() throws Exception {
4543 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
4544 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4545 BUBBLE_PREFERENCE_SELECTED);
4546 }
4547
4548 @Test
4549 public void testUserApprovedBubblesForPackageAll() throws Exception {
4550 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
4551 assertTrue(mBinderService.areBubblesAllowed(PKG));
4552 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4553 BUBBLE_PREFERENCE_ALL);
Mady Mellor9db685a2019-01-23 13:23:37 -08004554 }
4555
4556 @Test
4557 public void testUserRejectsBubblesForPackage() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004558 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4559 assertFalse(mBinderService.areBubblesAllowed(PKG));
Mady Mellor9db685a2019-01-23 13:23:37 -08004560 }
4561
4562 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004563 public void testIsCallerInstantApp_primaryUser() throws Exception {
4564 ApplicationInfo info = new ApplicationInfo();
4565 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4566 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004567 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004568
Julia Reynolds268647a2018-10-25 16:54:27 -04004569 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004570
4571 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004572 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004573 }
4574
4575 @Test
4576 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4577 ApplicationInfo info = new ApplicationInfo();
4578 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4579 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4580 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004581 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004582
Julia Reynolds268647a2018-10-25 16:54:27 -04004583 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004584 }
4585
4586 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004587 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4588 ApplicationInfo info = new ApplicationInfo();
4589 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004590 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004591 .thenReturn(info);
4592 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4593
4594 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4595
4596 info.privateFlags = 0;
4597 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4598 }
4599
4600 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004601 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4602 ApplicationInfo info = new ApplicationInfo();
4603 info.uid = Binder.getCallingUid();
4604 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4605 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4606
4607 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4608
4609 assertEquals(info.uid, actualUid);
4610 }
4611
4612 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004613 public void testResolveNotificationUid_sameApp() throws Exception {
4614 ApplicationInfo info = new ApplicationInfo();
4615 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004616 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004617
4618 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4619
4620 assertEquals(info.uid, actualUid);
4621 }
4622
4623 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004624 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004625 ApplicationInfo info = new ApplicationInfo();
4626 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004627 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004628
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004629 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4630
4631 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004632 }
4633
4634 @Test
4635 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4636 ApplicationInfo info = new ApplicationInfo();
4637 info.uid = 1356347;
4638 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4639
4640 try {
4641 mService.resolveNotificationUid("caller", "caller", 9, 0);
4642 fail("Incorrect uid didn't throw security exception");
4643 } catch (SecurityException e) {
4644 // yay
4645 }
4646 }
4647
4648 @Test
4649 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4650 int expectedUid = 123;
4651
4652 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4653 mService.setPreferencesHelper(mPreferencesHelper);
4654 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4655 .thenReturn(true);
4656
4657 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4658 }
4659
4660 @Test
4661 public void testResolveNotificationUid_androidAllowed() throws Exception {
4662 int expectedUid = 123;
4663
4664 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4665 // no delegate
4666
4667 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4668 }
4669
4670 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004671 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4672 final String notReal = "NOT REAL";
4673 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4674 PackageManager.NameNotFoundException.class);
4675 ApplicationInfo ai = new ApplicationInfo();
4676 ai.uid = -1;
4677 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4678
Julia Reynolds24edc002020-01-29 16:35:32 -05004679 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004680 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004681 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4682 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004683 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4684 fail("can't post notifications for nonexistent packages, even if you exist");
4685 } catch (SecurityException e) {
4686 // yay
4687 }
4688 }
4689
4690 @Test
4691 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4692 final String notReal = "NOT REAL";
4693 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4694 PackageManager.NameNotFoundException.class);
4695 ApplicationInfo ai = new ApplicationInfo();
4696 ai.uid = -1;
4697 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4698
4699 // unlike the post case, ignore instead of throwing
Julia Reynolds24edc002020-01-29 16:35:32 -05004700 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004701
4702 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4703 sbn.getId(), sbn.getUserId());
4704 }
4705
4706 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004707 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4708 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4709 // no delegate
4710
4711 try {
4712 mService.resolveNotificationUid("caller", "target", 9, 0);
4713 fail("Incorrect uid didn't throw security exception");
4714 } catch (SecurityException e) {
4715 // yay
4716 }
4717 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004718
4719 @Test
4720 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4721 Notification n = new Notification.Builder(mContext, "").build();
4722 n.flags |= FLAG_FOREGROUND_SERVICE;
4723
4724 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004725 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds564273f2018-09-13 15:53:11 -04004726 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4727
4728 mService.addEnqueuedNotification(r);
4729
4730 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004731 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004732
4733 waitForIdle();
4734
4735 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4736 }
4737
4738 @Test
4739 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4740 Notification n = new Notification.Builder(mContext, "").build();
4741 n.flags |= FLAG_FOREGROUND_SERVICE;
4742
4743 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004744 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds564273f2018-09-13 15:53:11 -04004745 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4746
4747 mService.addNotification(r);
4748
4749 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004750 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004751
4752 waitForIdle();
4753
4754 ArgumentCaptor<NotificationRecord> captor =
4755 ArgumentCaptor.forClass(NotificationRecord.class);
4756 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4757
4758 assertEquals(0, captor.getValue().getNotification().flags);
4759 }
Beverly58b24532018-10-02 09:08:23 -04004760
4761 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004762 public void testAllowForegroundCustomToasts() throws Exception {
Beverly58b24532018-10-02 09:08:23 -04004763 final String testPackage = "testPackageName";
4764 assertEquals(0, mService.mToastQueue.size());
4765 mService.isSystemUid = false;
4766
4767 // package is not suspended
4768 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4769 .thenReturn(false);
4770
4771 // notifications from this package are blocked by the user
4772 mService.setPreferencesHelper(mPreferencesHelper);
4773 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4774
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004775 setAppInForegroundForToasts(mUid, true);
Beverly58b24532018-10-02 09:08:23 -04004776
4777 // enqueue toast -> toast should still enqueue
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004778 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004779 new TestableToastCallback(), 2000, 0);
4780 assertEquals(1, mService.mToastQueue.size());
4781 }
4782
4783 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004784 public void testDisallowBackgroundCustomToasts() throws Exception {
4785 final String testPackage = "testPackageName";
4786 assertEquals(0, mService.mToastQueue.size());
4787 mService.isSystemUid = false;
4788
4789 // package is not suspended
4790 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4791 .thenReturn(false);
4792
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004793 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004794
4795 // enqueue toast -> no toasts enqueued
4796 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
4797 new TestableToastCallback(), 2000, 0);
4798 assertEquals(0, mService.mToastQueue.size());
4799 }
4800
4801 @Test
4802 public void testAllowForegroundTextToasts() throws Exception {
4803 final String testPackage = "testPackageName";
4804 assertEquals(0, mService.mToastQueue.size());
4805 mService.isSystemUid = false;
4806
4807 // package is not suspended
4808 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4809 .thenReturn(false);
4810
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004811 setAppInForegroundForToasts(mUid, true);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004812
4813 // enqueue toast -> toast should still enqueue
4814 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4815 "Text", 2000, 0, null);
4816 assertEquals(1, mService.mToastQueue.size());
4817 }
4818
4819 @Test
4820 public void testAllowBackgroundTextToasts() throws Exception {
4821 final String testPackage = "testPackageName";
4822 assertEquals(0, mService.mToastQueue.size());
4823 mService.isSystemUid = false;
4824
4825 // package is not suspended
4826 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4827 .thenReturn(false);
4828
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004829 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00004830
4831 // enqueue toast -> toast should still enqueue
4832 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4833 "Text", 2000, 0, null);
4834 assertEquals(1, mService.mToastQueue.size());
4835 }
4836
4837 @Test
4838 public void testTextToastsCallStatusBar() throws Exception {
4839 final String testPackage = "testPackageName";
4840 assertEquals(0, mService.mToastQueue.size());
4841 mService.isSystemUid = false;
4842
4843 // package is not suspended
4844 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4845 .thenReturn(false);
4846
4847 // enqueue toast -> no toasts enqueued
4848 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
4849 "Text", 2000, 0, null);
Bernardo Rufino78f5d832020-04-03 11:50:23 +01004850 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
Bernardo Rufino18725b62020-01-21 14:12:43 +00004851 }
4852
4853 @Test
Beverly58b24532018-10-02 09:08:23 -04004854 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4855 final String testPackage = "testPackageName";
4856 assertEquals(0, mService.mToastQueue.size());
4857 mService.isSystemUid = false;
4858
4859 // package is suspended
4860 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4861 .thenReturn(true);
4862
4863 // notifications from this package are NOT blocked by the user
4864 mService.setPreferencesHelper(mPreferencesHelper);
4865 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4866
4867 // enqueue toast -> no toasts 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(0, mService.mToastQueue.size());
4871 }
4872
4873 @Test
4874 public void testDisallowToastsFromBlockedApps() throws Exception {
4875 final String testPackage = "testPackageName";
4876 assertEquals(0, mService.mToastQueue.size());
4877 mService.isSystemUid = false;
4878
4879 // package is not suspended
4880 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4881 .thenReturn(false);
4882
4883 // notifications from this package are blocked by the user
4884 mService.setPreferencesHelper(mPreferencesHelper);
4885 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4886
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004887 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04004888
4889 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004890 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004891 new TestableToastCallback(), 2000, 0);
4892 assertEquals(0, mService.mToastQueue.size());
4893 }
4894
4895 @Test
4896 public void testAlwaysAllowSystemToasts() throws Exception {
4897 final String testPackage = "testPackageName";
4898 assertEquals(0, mService.mToastQueue.size());
4899 mService.isSystemUid = true;
4900
4901 // package is suspended
4902 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4903 .thenReturn(true);
4904
4905 // notifications from this package ARE blocked by the user
4906 mService.setPreferencesHelper(mPreferencesHelper);
4907 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4908
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004909 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04004910
4911 // enqueue toast -> system toast can still be enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004912 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004913 new TestableToastCallback(), 2000, 0);
4914 assertEquals(1, mService.mToastQueue.size());
4915 }
Tony Mak29996702018-11-26 16:23:34 +00004916
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004917 private void setAppInForegroundForToasts(int uid, boolean inForeground) {
4918 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
4919 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
4920 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
4921 }
4922
Tony Mak29996702018-11-26 16:23:34 +00004923 @Test
Alex Mang509e5542020-01-03 13:06:40 -08004924 public void testOnPanelRevealedAndHidden() {
4925 int items = 5;
4926 mService.mNotificationDelegate.onPanelRevealed(false, items);
4927 verify(mAssistants, times(1)).onPanelRevealed(eq(items));
4928
4929 mService.mNotificationDelegate.onPanelHidden();
4930 verify(mAssistants, times(1)).onPanelHidden();
Will Brockman9918db92020-03-06 16:48:39 -05004931
4932 assertEquals(2, mNotificationRecordLogger.numCalls());
4933 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
4934 mNotificationRecordLogger.event(0));
4935 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
4936 mNotificationRecordLogger.event(1));
Alex Mang509e5542020-01-03 13:06:40 -08004937 }
4938
4939 @Test
Tony Mak29996702018-11-26 16:23:34 +00004940 public void testOnNotificationSmartReplySent() {
4941 final int replyIndex = 2;
4942 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004943 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004944 final boolean generatedByAssistant = true;
4945
4946 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004947 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004948 mService.addNotification(r);
4949
4950 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004951 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4952 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004953 verify(mAssistants).notifyAssistantSuggestedReplySent(
Julia Reynolds24edc002020-01-29 16:35:32 -05004954 eq(r.getSbn()), eq(reply), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05004955 assertEquals(1, mNotificationRecordLogger.numCalls());
4956 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
4957 mNotificationRecordLogger.event(0));
Tony Mak29996702018-11-26 16:23:34 +00004958 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004959
4960 @Test
4961 public void testOnNotificationActionClick() {
4962 final int actionIndex = 2;
4963 final Notification.Action action =
4964 new Notification.Action.Builder(null, "text", null).build();
4965 final boolean generatedByAssistant = false;
4966
4967 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4968 mService.addNotification(r);
4969
4970 NotificationVisibility notificationVisibility =
4971 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4972 mService.mNotificationDelegate.onNotificationActionClick(
4973 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4974 generatedByAssistant);
4975 verify(mAssistants).notifyAssistantActionClicked(
Julia Reynolds24edc002020-01-29 16:35:32 -05004976 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05004977
4978 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockman2a2c0c92020-05-04 13:58:28 -04004979 assertEquals(
4980 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2,
4981 mNotificationRecordLogger.event(0));
4982 }
4983
4984 @Test
4985 public void testOnAssistantNotificationActionClick() {
4986 final int actionIndex = 1;
4987 final Notification.Action action =
4988 new Notification.Action.Builder(null, "text", null).build();
4989 final boolean generatedByAssistant = true;
4990
4991 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4992 mService.addNotification(r);
4993
4994 NotificationVisibility notificationVisibility =
4995 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4996 mService.mNotificationDelegate.onNotificationActionClick(
4997 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4998 generatedByAssistant);
4999 verify(mAssistants).notifyAssistantActionClicked(
5000 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
5001
5002 assertEquals(1, mNotificationRecordLogger.numCalls());
5003 assertEquals(
5004 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1,
Will Brockman9918db92020-03-06 16:48:39 -05005005 mNotificationRecordLogger.event(0));
Tony Mak7d4b3a52018-11-27 17:29:36 +00005006 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00005007
5008 @Test
5009 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
5010 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5011 mService.addNotification(r);
5012
Gustav Senntona8e38aa2019-01-22 14:55:39 +00005013 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5014 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00005015 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
5016 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
5017 };
5018 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
5019 new NotificationVisibility[0]);
5020
5021 assertEquals(1, mService.countLogSmartSuggestionsVisible);
5022 }
5023
5024 @Test
5025 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
5026 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5027 mService.addNotification(r);
5028
Gustav Senntona8e38aa2019-01-22 14:55:39 +00005029 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5030 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00005031
5032 assertEquals(0, mService.countLogSmartSuggestionsVisible);
5033 }
5034
5035 @Test
5036 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
5037 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5038 mService.addNotification(r);
5039
Julia Reynolds95334132018-12-19 11:15:35 -05005040 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00005041 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
5042 };
5043 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
5044 new NotificationVisibility[0]);
5045
5046 assertEquals(0, mService.countLogSmartSuggestionsVisible);
5047 }
Julia Reynolds95334132018-12-19 11:15:35 -05005048
Colin Cross5ea7fb72019-12-18 17:16:36 -08005049 @Test
Julia Reynolds95334132018-12-19 11:15:35 -05005050 public void testReportSeen_delegated() {
5051 Notification.Builder nb =
5052 new Notification.Builder(mContext, mTestNotificationChannel.getId())
5053 .setContentTitle("foo")
5054 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5055
5056 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005057 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds95334132018-12-19 11:15:35 -05005058 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5059
5060 mService.reportSeen(r);
5061 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
5062
5063 }
5064
5065 @Test
5066 public void testReportSeen_notDelegated() {
5067 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5068
5069 mService.reportSeen(r);
5070 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
5071 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005072
5073 @Test
5074 public void testNotificationStats_notificationError() {
5075 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5076 mService.addNotification(r);
5077
Julia Reynolds24edc002020-01-29 16:35:32 -05005078 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
5079 r.getSbn().getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005080 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04005081 UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005082 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5083 mService.addEnqueuedNotification(update);
Julia Reynolds24edc002020-01-29 16:35:32 -05005084 assertNull(update.getSbn().getNotification().getSmallIcon());
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005085
5086 NotificationManagerService.PostNotificationRunnable runnable =
5087 mService.new PostNotificationRunnable(update.getKey());
5088 runnable.run();
5089 waitForIdle();
5090
5091 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
5092 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
5093 assertNotNull(captor.getValue());
5094 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005095
5096 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005097 public void testCanNotifyAsUser_crossUser() throws Exception {
5098 // same user no problem
5099 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
5100
5101 // cross user, no permission, problem
5102 try {
5103 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5104 fail("Should not be callable cross user without cross user permission");
5105 } catch (SecurityException e) {
5106 // good
5107 }
5108
5109 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005110 enableInteractAcrossUsers();
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005111 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5112 }
5113
5114 @Test
Julia Reynoldse61758a2020-06-10 10:26:44 -04005115 public void testGetNotificationChannels_crossUser() throws Exception {
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005116 // same user no problem
5117 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
5118
5119 // cross user, no permission, problem
5120 try {
5121 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5122 fail("Should not be callable cross user without cross user permission");
5123 } catch (SecurityException e) {
5124 // good
5125 }
5126
5127 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005128 enableInteractAcrossUsers();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005129 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5130 }
5131
5132 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00005133 public void setDefaultAssistantForUser_fromConfigXml() {
5134 clearDeviceConfig();
5135 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04005136 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005137 when(mResources
5138 .getString(
5139 com.android.internal.R.string.config_defaultAssistantAccessComponent))
5140 .thenReturn(xmlConfig.flattenToString());
5141 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005142 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
5143 .thenReturn(components);
5144 when(mAssistants.getDefaultComponents())
5145 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00005146 mService.setNotificationAssistantAccessGrantedCallback(
5147 mNotificationAssistantAccessGrantedCallback);
5148
Jay Aliomer4204f252019-08-26 11:36:53 -04005149
Tony Mak9a3c1f12019-03-04 16:04:42 +00005150 mService.setDefaultAssistantForUser(0);
5151
5152 verify(mNotificationAssistantAccessGrantedCallback)
5153 .onGranted(eq(xmlConfig), eq(0), eq(true));
5154 }
5155
5156 @Test
5157 public void setDefaultAssistantForUser_fromDeviceConfig() {
5158 ComponentName xmlConfig = new ComponentName("xml", "config");
5159 ComponentName deviceConfig = new ComponentName("device", "config");
5160 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5161 when(mResources
5162 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5163 .thenReturn(xmlConfig.flattenToString());
5164 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005165 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00005166 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04005167 when(mAssistants.getDefaultComponents())
5168 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005169 mService.setNotificationAssistantAccessGrantedCallback(
5170 mNotificationAssistantAccessGrantedCallback);
5171
5172 mService.setDefaultAssistantForUser(0);
5173
5174 verify(mNotificationAssistantAccessGrantedCallback)
5175 .onGranted(eq(deviceConfig), eq(0), eq(true));
5176 }
5177
5178 @Test
5179 public void setDefaultAssistantForUser_deviceConfigInvalid() {
5180 ComponentName xmlConfig = new ComponentName("xml", "config");
5181 ComponentName deviceConfig = new ComponentName("device", "config");
5182 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5183 when(mResources
5184 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5185 .thenReturn(xmlConfig.flattenToString());
5186 when(mContext.getResources()).thenReturn(mResources);
5187 // Only xmlConfig is valid, deviceConfig is not.
5188 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04005189 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
5190 when(mAssistants.getDefaultComponents())
5191 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005192 mService.setNotificationAssistantAccessGrantedCallback(
5193 mNotificationAssistantAccessGrantedCallback);
5194
5195 mService.setDefaultAssistantForUser(0);
5196
5197 verify(mNotificationAssistantAccessGrantedCallback)
5198 .onGranted(eq(xmlConfig), eq(0), eq(true));
5199 }
5200
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005201 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04005202 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
5203 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
5204 generateResetComponentValues();
5205 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
5206 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5207 ComponentName deviceConfig1 = new ComponentName("device", "config1");
5208 ComponentName deviceConfig2 = new ComponentName("device", "config2");
5209 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
5210 changes.put(false, new ArrayList());
5211 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
5212 mService.getBinderService().clearData("device", 0, false);
5213 verify(mAssistants, times(1))
5214 .setPackageOrComponentEnabled(
5215 eq("device/config2"),
5216 eq(0), eq(true), eq(false));
5217 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5218 eq("device"), eq(0), eq(false), eq(true));
5219 }
5220
5221 @Test
5222 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
5223 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
5224 generateResetComponentValues();
5225 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
5226 ComponentName deviceConfig = new ComponentName("device", "config");
5227 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5228 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
5229 changes.put(false, new ArrayList());
5230 when(mListeners.resetComponents(anyString(), anyInt()))
5231 .thenReturn(changes);
5232 mService.getBinderService().clearData("device", 0, false);
5233 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5234 eq("device"), eq(0), eq(false), eq(true));
5235 }
5236
5237 @Test
5238 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
5239 ComponentName deviceConfig = new ComponentName("device", "config");
5240 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
5241 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
5242 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
5243 mService.getBinderService().clearData("device", 0, false);
5244 verify(mConditionProviders, times(1)).resetPackage(
5245 eq("device"), eq(0));
5246 }
5247
5248 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07005249 public void testFlagBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005250 setUpPrefsForBubbles(PKG, mUid,
5251 true /* global */,
5252 BUBBLE_PREFERENCE_ALL /* app */,
5253 true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07005254
Mady Mellor9e923e12019-12-17 16:08:46 -08005255 NotificationRecord nr =
5256 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
Mady Mellor65dcaa92019-04-03 12:21:44 -07005257
Julia Reynolds24edc002020-01-29 16:35:32 -05005258 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5259 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005260 waitForIdle();
5261
5262 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5263 assertEquals(1, notifs.length);
5264 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
5265 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005266 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005267 }
5268
5269 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07005270 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005271 setUpPrefsForBubbles(PKG, mUid,
5272 true /* global */,
5273 BUBBLE_PREFERENCE_NONE /* app */,
5274 true /* channel */);
Mady Mellorc6820342019-05-20 12:04:36 -07005275
Mady Mellor9e923e12019-12-17 16:08:46 -08005276 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5277 "testFlagBubble_noFlag_appNotAllowed");
Mady Mellorc6820342019-05-20 12:04:36 -07005278
Julia Reynolds24edc002020-01-29 16:35:32 -05005279 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5280 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorc6820342019-05-20 12:04:36 -07005281 waitForIdle();
5282
5283 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5284 assertEquals(1, notifs.length);
5285 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
5286 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005287 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorc6820342019-05-20 12:04:36 -07005288 }
5289
5290 @Test
Mady Mellor9e923e12019-12-17 16:08:46 -08005291 public void testFlagBubbleNotifs_noFlag_whenAppForeground() 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 Mellorbe797962019-04-01 16:04:24 -07005297 // Notif with bubble metadata but not our other misc requirements
Mady Mellor9e923e12019-12-17 16:08:46 -08005298 Notification.Builder nb = new Notification.Builder(mContext,
5299 mTestNotificationChannel.getId())
5300 .setContentTitle("foo")
5301 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Mady Mellora92268c2020-03-09 17:25:08 -07005302 .setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -08005303 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005304 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor9e923e12019-12-17 16:08:46 -08005305 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellorbe797962019-04-01 16:04:24 -07005306
5307 // Say we're foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05005308 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellorbe797962019-04-01 16:04:24 -07005309 IMPORTANCE_FOREGROUND);
Julia Reynolds24edc002020-01-29 16:35:32 -05005310 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5311 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005312 waitForIdle();
5313
Mady Mellor9e923e12019-12-17 16:08:46 -08005314 // if notif isn't configured properly it doesn't get to bubble just because app is
5315 // foreground.
Mady Mellorbe797962019-04-01 16:04:24 -07005316 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005317 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005318 }
5319
5320 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005321 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005322 setUpPrefsForBubbles(PKG, mUid,
5323 true /* global */,
5324 BUBBLE_PREFERENCE_ALL /* app */,
5325 true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005326
Mady Mellor9e923e12019-12-17 16:08:46 -08005327 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5328 "testFlagBubbleNotifs_flag_messaging");
Mady Mellorbe797962019-04-01 16:04:24 -07005329
Julia Reynolds24edc002020-01-29 16:35:32 -05005330 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5331 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005332 waitForIdle();
5333
5334 // yes allowed, yes messaging, yes bubble
5335 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005336 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005337 }
5338
5339 @Test
Mady Mellor6ce11e72020-05-29 14:07:24 -07005340 public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException {
5341 setUpPrefsForBubbles(PKG, mUid,
5342 true /* global */,
5343 BUBBLE_PREFERENCE_ALL /* app */,
5344 true /* channel */);
5345
5346 Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false);
5347 nb.setShortcutId(null);
5348 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5349 null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005350 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor6ce11e72020-05-29 14:07:24 -07005351
5352 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
5353 sbn.getId(), sbn.getNotification(), sbn.getUserId());
5354 waitForIdle();
5355
5356 // no shortcut no bubble
5357 assertFalse(mService.getNotificationRecord(
5358 sbn.getKey()).getNotification().isBubbleNotification());
5359 }
5360
5361 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005362 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005363 setUpPrefsForBubbles(PKG, mUid,
5364 true /* global */,
5365 BUBBLE_PREFERENCE_NONE /* app */,
5366 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005367
Mady Mellor9e923e12019-12-17 16:08:46 -08005368 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5369 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005370
5371 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005372 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5373 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005374 waitForIdle();
5375
5376 // not allowed, no bubble
5377 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005378 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005379 }
5380
5381 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005382 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005383 setUpPrefsForBubbles(PKG, mUid,
5384 true /* global */,
5385 BUBBLE_PREFERENCE_ALL /* app */,
5386 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005387
Mady Mellor9e923e12019-12-17 16:08:46 -08005388 // Messaging notif WITHOUT bubble metadata
5389 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
5390 null /* groupKey */, false /* isSummary */);
5391
5392 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5393 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005394 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor9e923e12019-12-17 16:08:46 -08005395 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005396
5397 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005398 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5399 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005400 waitForIdle();
5401
5402 // no bubble metadata, no bubble
5403 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005404 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005405 }
5406
5407 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005408 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005409 setUpPrefsForBubbles(PKG, mUid,
5410 true /* global */,
5411 BUBBLE_PREFERENCE_ALL /* app */,
5412 false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005413
Mady Mellor9e923e12019-12-17 16:08:46 -08005414 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5415 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
Mady Mellora92268c2020-03-09 17:25:08 -07005416 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005417
5418 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005419 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5420 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005421 waitForIdle();
5422
5423 // channel not allowed, no bubble
5424 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005425 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005426 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005427
Mady Mellor49b1bf12019-03-29 12:00:02 -07005428 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005429 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
Mady Mellor49b1bf12019-03-29 12:00:02 -07005430 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005431 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005432
5433 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005434 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5435 "testAppCancelNotifications_cancelsBubbles",
Julia Reynolds24edc002020-01-29 16:35:32 -05005436 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
5437 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005438 waitForIdle();
5439
5440 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5441 assertEquals(1, notifs.length);
5442 assertEquals(1, mService.getNotificationRecordCount());
5443
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005444 mBinderService.cancelNotificationWithTag(PKG, PKG,
Julia Reynolds24edc002020-01-29 16:35:32 -05005445 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
5446 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005447 waitForIdle();
5448
5449 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5450 assertEquals(0, notifs2.length);
5451 assertEquals(0, mService.getNotificationRecordCount());
5452 }
5453
5454 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005455 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
5456 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5457 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5458 mService.addNotification(nr);
5459
5460 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
5461 waitForIdle();
5462
5463 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5464 assertEquals(0, notifs.length);
5465 assertEquals(0, mService.getNotificationRecordCount());
5466 }
5467
5468 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005469 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5470 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5471 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005472 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005473
5474 mService.addNotification(nrNormal);
5475 mService.addNotification(nrBubble);
5476
5477 mService.getBinderService().cancelNotificationsFromListener(null, null);
5478 waitForIdle();
5479
5480 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5481 assertEquals(1, notifs.length);
5482 assertEquals(1, mService.getNotificationRecordCount());
5483 }
5484
5485 @Test
Lyn Han675570a2020-06-05 23:31:22 -07005486 public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception {
5487 // Add non-bubble notif
5488 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5489 mService.addNotification(nr);
Mady Mellor49b1bf12019-03-29 12:00:02 -07005490
Lyn Han675570a2020-06-05 23:31:22 -07005491 // Cancel via listener
5492 String[] keys = {nr.getSbn().getKey()};
Mady Mellor49b1bf12019-03-29 12:00:02 -07005493 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5494 waitForIdle();
5495
Lyn Han675570a2020-06-05 23:31:22 -07005496 // Notif not active anymore
5497 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5498 assertEquals(0, notifs.length);
5499 assertEquals(0, mService.getNotificationRecordCount());
5500 // Cancel event is logged
5501 assertEquals(1, mNotificationRecordLogger.numCalls());
5502 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
5503 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
5504 }
5505
5506 @Test
5507 public void testCancelNotificationsFromListener_suppressesBubble() throws Exception {
5508 // Add bubble notif
5509 setUpPrefsForBubbles(PKG, mUid,
5510 true /* global */,
5511 BUBBLE_PREFERENCE_ALL /* app */,
5512 true /* channel */);
5513 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5514
5515 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5516 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5517 waitForIdle();
5518
5519 // Cancel via listener
5520 String[] keys = {nr.getSbn().getKey()};
5521 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5522 waitForIdle();
5523
5524 // Bubble notif active and suppressed
Mady Mellor49b1bf12019-03-29 12:00:02 -07005525 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5526 assertEquals(1, notifs.length);
5527 assertEquals(1, mService.getNotificationRecordCount());
Lyn Han675570a2020-06-05 23:31:22 -07005528 assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005529 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005530
Julia Reynolds4214da92019-04-10 15:04:06 -04005531 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005532 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
5533 // GIVEN a notification bubble
5534 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5535 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5536 mService.addNotification(nr);
5537
5538 // WHEN the status bar clears all notifications
5539 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
5540 nr.getSbn().getUserId());
5541 waitForIdle();
5542
5543 // THEN the bubble notification does not get removed
5544 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5545 assertEquals(1, notifs.length);
5546 assertEquals(1, mService.getNotificationRecordCount());
5547 }
5548
5549
5550 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005551 public void testGetAllowedAssistantAdjustments() throws Exception {
5552 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005553 assertNotNull(capabilities);
5554
5555 for (int i = capabilities.size() - 1; i >= 0; i--) {
5556 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005557 mBinderService.disallowAssistantAdjustment(capability);
5558 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5559 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005560 assertNotNull(currentCapabilities);
5561 assertFalse(currentCapabilities.contains(capability));
5562 }
5563 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005564
Julia Reynolds4214da92019-04-10 15:04:06 -04005565 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005566 public void testAdjustRestrictedKey() throws Exception {
5567 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005568 mService.addNotification(r);
5569 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005570
5571 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5572 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5573
5574 Bundle signals = new Bundle();
5575 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5576 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
Julia Reynolds24edc002020-01-29 16:35:32 -05005577 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005578 "", r.getUser().getIdentifier());
5579
5580 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5581 r.applyAdjustments();
5582
5583 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5584 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5585 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005586
Julia Reynolds4214da92019-04-10 15:04:06 -04005587 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005588 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005589 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5590 .thenReturn(true);
5591 mService.setZenHelper(mock(ZenModeHelper.class));
5592 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005593 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5594 boolean isEnabled = true;
5595 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5596 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5597
5598 try {
5599 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005600 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005601 } catch (IllegalArgumentException e) {
5602 // yay
5603 }
5604
5605 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5606 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5607 mBinderService.addAutomaticZenRule(rule);
5608
5609 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5610 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5611 mBinderService.addAutomaticZenRule(rule);
5612 }
5613
Julia Reynolds4214da92019-04-10 15:04:06 -04005614 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005615 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5616 try {
5617 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5618 mUid + UserHandle.PER_USER_RANGE);
5619 fail("Cannot call cross user without permission");
5620 } catch (SecurityException e) {
5621 // pass
5622 }
5623
5624 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005625 enableInteractAcrossUsers();
Julia Reynolds657d1642019-03-27 12:15:57 -04005626 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5627 mUid + UserHandle.PER_USER_RANGE);
5628 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005629
Julia Reynolds4214da92019-04-10 15:04:06 -04005630 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005631 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5632 try {
Mady Mellora92268c2020-03-09 17:25:08 -07005633 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005634 mUid + UserHandle.PER_USER_RANGE);
5635 fail("Cannot call cross user without permission");
5636 } catch (SecurityException e) {
5637 // pass
5638 }
5639
5640 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005641 enableInteractAcrossUsers();
Mady Mellora92268c2020-03-09 17:25:08 -07005642 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005643 mUid + UserHandle.PER_USER_RANGE);
5644 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005645
Will Brockmancfd98302020-01-29 15:57:30 -05005646 private void enableInteractAcrossUsers() {
5647 TestablePermissions perms = mContext.getTestablePermissions();
5648 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5649 }
5650
Mady Mellora54e9fa2019-04-18 13:26:18 -07005651 @Test
5652 public void testNotificationBubbleChanged_false() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005653 setUpPrefsForBubbles(PKG, mUid,
5654 true /* global */,
5655 BUBBLE_PREFERENCE_ALL /* app */,
5656 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005657
Mady Mellor9e923e12019-12-17 16:08:46 -08005658 // Notif with bubble metadata
5659 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5660 "testNotificationBubbleChanged_false");
Mady Mellora54e9fa2019-04-18 13:26:18 -07005661
Julia Reynolds24edc002020-01-29 16:35:32 -05005662 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5663 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005664 waitForIdle();
5665
Mady Mellor66efd5e2019-05-15 13:38:11 -07005666 // Reset as this is called when the notif is first sent
5667 reset(mListeners);
5668
Mady Mellora54e9fa2019-04-18 13:26:18 -07005669 // First we were a bubble
5670 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5671 assertEquals(1, notifsBefore.length);
5672 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5673
5674 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005675 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005676 waitForIdle();
5677
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005678 // Make sure we are not a bubble
5679 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5680 assertEquals(1, notifsAfter.length);
5681 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005682 }
5683
5684 @Test
5685 public void testNotificationBubbleChanged_true() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005686 setUpPrefsForBubbles(PKG, mUid,
5687 true /* global */,
5688 BUBBLE_PREFERENCE_ALL /* app */,
5689 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005690
Mady Mellor9e923e12019-12-17 16:08:46 -08005691 // Notif that is not a bubble
Mady Mellora54e9fa2019-04-18 13:26:18 -07005692 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08005693 1, null, false);
Julia Reynolds24edc002020-01-29 16:35:32 -05005694 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5695 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005696 waitForIdle();
5697
5698 // Would be a normal notification because wouldn't have met requirements to bubble
5699 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5700 assertEquals(1, notifsBefore.length);
5701 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5702
Mady Mellor9e923e12019-12-17 16:08:46 -08005703 // Update the notification to be message style / meet bubble requirements
5704 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
Julia Reynolds24edc002020-01-29 16:35:32 -05005705 nr.getSbn().getTag());
5706 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
5707 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
Mady Mellor9e923e12019-12-17 16:08:46 -08005708 waitForIdle();
Mady Mellora54e9fa2019-04-18 13:26:18 -07005709
Mady Mellor66efd5e2019-05-15 13:38:11 -07005710 // Reset as this is called when the notif is first sent
5711 reset(mListeners);
5712
Mady Mellora54e9fa2019-04-18 13:26:18 -07005713 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005714 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005715 waitForIdle();
5716
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005717 // Make sure we are a bubble
5718 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5719 assertEquals(1, notifsAfter.length);
5720 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005721 }
5722
5723 @Test
5724 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005725 setUpPrefsForBubbles(PKG, mUid,
5726 true /* global */,
5727 BUBBLE_PREFERENCE_ALL /* app */,
5728 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005729
5730 // Notif that is not a bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005731 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005732 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5733 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005734 waitForIdle();
5735
Mady Mellor66efd5e2019-05-15 13:38:11 -07005736 // Reset as this is called when the notif is first sent
5737 reset(mListeners);
5738
Mady Mellora54e9fa2019-04-18 13:26:18 -07005739 // Would be a normal notification because wouldn't have met requirements to bubble
5740 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5741 assertEquals(1, notifsBefore.length);
5742 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5743
5744 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005745 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005746 waitForIdle();
5747
5748 // We still wouldn't be a bubble because the notification didn't meet requirements
5749 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5750 assertEquals(1, notifsAfter.length);
5751 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5752 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005753
5754 @Test
Mady Mellor13f9bc82020-03-24 19:09:28 -07005755 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005756 setUpPrefsForBubbles(PKG, mUid,
5757 true /* global */,
5758 BUBBLE_PREFERENCE_ALL /* app */,
5759 true /* channel */);
5760
Mady Mellor13f9bc82020-03-24 19:09:28 -07005761 // Notif with bubble metadata
5762 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5763 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
5764
5765 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5766 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5767 waitForIdle();
5768 // Flag shouldn't be modified
5769 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5770 assertFalse(recordToCheck.isFlagBubbleRemoved());
5771
5772 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005773 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005774 waitForIdle();
5775 // Flag should be modified
5776 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5777 assertTrue(recordToCheck.isFlagBubbleRemoved());
5778
5779
5780 // Update the notif
5781 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5782 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5783 waitForIdle();
5784 // And the flag is reset
5785 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5786 assertFalse(recordToCheck.isFlagBubbleRemoved());
5787 }
5788
5789 @Test
5790 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005791 setUpPrefsForBubbles(PKG, mUid,
5792 true /* global */,
5793 BUBBLE_PREFERENCE_ALL /* app */,
5794 true /* channel */);
5795
Mady Mellor13f9bc82020-03-24 19:09:28 -07005796 // Notif with bubble metadata
5797 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5798 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
5799
5800 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5801 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5802 waitForIdle();
5803 // Flag shouldn't be modified
5804 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5805 assertFalse(recordToCheck.isFlagBubbleRemoved());
5806
5807 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005808 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005809 waitForIdle();
5810 // Flag should be modified
5811 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5812 assertTrue(recordToCheck.isFlagBubbleRemoved());
5813
5814 // Notify we are a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005815 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005816 waitForIdle();
5817 // And the flag is reset
5818 assertFalse(recordToCheck.isFlagBubbleRemoved());
5819 }
5820
5821 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -08005822 public void testOnBubbleNotificationSuppressionChanged() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005823 setUpPrefsForBubbles(PKG, mUid,
5824 true /* global */,
5825 BUBBLE_PREFERENCE_ALL /* app */,
5826 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08005827
Mady Mellorf44b6832020-01-14 13:26:14 -08005828 // Bubble notification
5829 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5830
Julia Reynolds24edc002020-01-29 16:35:32 -05005831 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5832 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorf44b6832020-01-14 13:26:14 -08005833 waitForIdle();
5834
5835 // NOT suppressed
5836 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5837 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5838
5839 // Reset as this is called when the notif is first sent
5840 reset(mListeners);
5841
5842 // Test: update suppression to true
5843 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
5844 waitForIdle();
5845
5846 // Check
5847 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5848 assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
5849
5850 // Reset to check again
5851 reset(mListeners);
5852
5853 // Test: update suppression to false
5854 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
5855 waitForIdle();
5856
5857 // Check
5858 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
5859 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
5860 }
5861
5862 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005863 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
5864 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5865 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005866 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005867 waitForIdle();
5868
5869 // A notification exists for the given record
5870 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5871 assertEquals(1, notifsBefore.length);
5872
5873 reset(mPackageManager);
5874
5875 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5876
5877 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005878 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5879 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005880
5881 // Grant permission called for the UID of SystemUI under the target user ID
5882 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005883 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5884 anyInt(), eq(nr.getSbn().getUserId()));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005885 }
5886
5887 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005888 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
5889 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5890 waitForIdle();
5891
5892 // No notifications exist for the given record
5893 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5894 assertEquals(0, notifsBefore.length);
5895
5896 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5897 int uid = 0; // sysui on primary user
5898
5899 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005900 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5901 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005902
5903 // Grant permission still called if no NotificationRecord exists for the given key
5904 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005905 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5906 anyInt(), eq(nr.getSbn().getUserId()));
Aran Ink979c9762019-10-24 16:09:45 -04005907 }
5908
5909 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005910 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
5911 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5912 NotificationRecord nr =
5913 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
5914 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005915 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005916 waitForIdle();
5917
5918 // A notification exists for the given record
5919 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5920 assertEquals(1, notifsBefore.length);
5921
5922 reset(mPackageManager);
5923
5924 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5925
5926 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005927 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5928 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005929
5930 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5931 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005932 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
5933 anyInt(), eq(UserHandle.USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005934 }
5935
5936 @Test
5937 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
5938 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5939 int otherUserId = 11;
5940 NotificationRecord nr =
5941 generateNotificationRecord(mTestNotificationChannel, otherUserId);
5942 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05005943 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005944 waitForIdle();
5945
5946 // A notification exists for the given record
5947 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5948 assertEquals(1, notifsBefore.length);
5949
5950 reset(mPackageManager);
5951
5952 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5953
5954 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04005955 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04005956 String sysuiPackage = "sysui";
5957 final String[] sysuiPackages = new String[] { sysuiPackage };
5958 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
5959
5960 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
5961 // time this is called
5962 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
5963 .thenReturn(otherUserUid);
5964
Aran Ink979c9762019-10-24 16:09:45 -04005965 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005966 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005967
5968 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5969 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05005970 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
Aran Inkfd2bfd32019-10-04 16:30:01 -04005971 eq(otherUserId));
5972 }
5973
5974 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005975 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
5976 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5977 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005978
Aran Ink979c9762019-10-24 16:09:45 -04005979 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5980 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005981
Aran Ink979c9762019-10-24 16:09:45 -04005982 // create an inline record with two uris in it
5983 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005984 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5985 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005986 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05005987 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
5988 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005989
Aran Ink979c9762019-10-24 16:09:45 -04005990 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5991 assertNotNull(record); // record exists
5992 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04005993
Julia Reynolds24edc002020-01-29 16:35:32 -05005994 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
5995 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04005996
5997 // permissionOwner destroyed
5998 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5999 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
6000 }
6001
6002
6003 @Test
6004 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
6005 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6006 reset(mPackageManager);
6007
Julia Reynolds24edc002020-01-29 16:35:32 -05006008 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
6009 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006010
6011 // no permissionOwner destroyed
6012 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
6013 any(), eq(null), eq(~0), eq(nr.getUserId()));
6014 }
6015
6016 @Test
6017 public void testClearInlineReplyUriPermission_userAll() throws Exception {
6018 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
6019 UserHandle.USER_ALL);
6020 reset(mPackageManager);
6021
6022 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6023 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
6024
6025 // create an inline record a uri in it
6026 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006027 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6028 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006029
6030 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
6031 assertNotNull(record); // record exists
6032
Julia Reynolds24edc002020-01-29 16:35:32 -05006033 mService.mNotificationDelegate.clearInlineReplyUriPermissions(
6034 nr.getKey(), nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006035
6036 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
6037 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
6038 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04006039 }
6040
6041 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006042 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006043 setUpPrefsForBubbles(PKG, mUid,
6044 true /* global */,
6045 BUBBLE_PREFERENCE_ALL /* app */,
6046 true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006047
Mady Mellor9e923e12019-12-17 16:08:46 -08006048 // And we are low ram
6049 when(mActivityManager.isLowRamDevice()).thenReturn(true);
6050
6051 // Notification that would typically bubble
6052 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6053 "testNotificationBubbles_disabled_lowRamDevice");
Julia Reynolds24edc002020-01-29 16:35:32 -05006054 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6055 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006056 waitForIdle();
6057
Mady Mellor9e923e12019-12-17 16:08:46 -08006058 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006059 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6060 assertEquals(1, notifsAfter.length);
6061 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006062 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04006063
6064 @Test
6065 public void testRemoveLargeRemoteViews() throws Exception {
6066 int removeSize = mContext.getResources().getInteger(
6067 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
6068
6069 RemoteViews rv = mock(RemoteViews.class);
6070 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
6071 when(rv.clone()).thenReturn(rv);
6072 RemoteViews rv1 = mock(RemoteViews.class);
6073 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
6074 when(rv1.clone()).thenReturn(rv1);
6075 RemoteViews rv2 = mock(RemoteViews.class);
6076 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
6077 when(rv2.clone()).thenReturn(rv2);
6078 RemoteViews rv3 = mock(RemoteViews.class);
6079 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
6080 when(rv3.clone()).thenReturn(rv3);
6081 RemoteViews rv4 = mock(RemoteViews.class);
6082 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
6083 when(rv4.clone()).thenReturn(rv4);
6084 // note: different!
6085 RemoteViews rv5 = mock(RemoteViews.class);
6086 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
6087 when(rv5.clone()).thenReturn(rv5);
6088
6089 Notification np = new Notification.Builder(mContext, "test")
6090 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6091 .setContentText("test")
6092 .setCustomContentView(rv)
6093 .setCustomBigContentView(rv1)
6094 .setCustomHeadsUpContentView(rv2)
6095 .build();
6096 Notification n = new Notification.Builder(mContext, "test")
6097 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6098 .setContentText("test")
6099 .setCustomContentView(rv3)
6100 .setCustomBigContentView(rv4)
6101 .setCustomHeadsUpContentView(rv5)
6102 .setPublicVersion(np)
6103 .build();
6104
6105 assertNotNull(np.contentView);
6106 assertNotNull(np.bigContentView);
6107 assertNotNull(np.headsUpContentView);
6108
6109 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
6110 assertNotNull(n.publicVersion.contentView);
6111 assertNotNull(n.publicVersion.bigContentView);
6112 assertNotNull(n.publicVersion.headsUpContentView);
6113
6114 mService.fixNotification(n, PKG, "tag", 9, 0);
6115
6116 assertNull(n.contentView);
6117 assertNull(n.bigContentView);
6118 assertNotNull(n.headsUpContentView);
6119 assertNull(n.publicVersion.contentView);
6120 assertNull(n.publicVersion.bigContentView);
6121 assertNull(n.publicVersion.headsUpContentView);
6122
6123 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
6124 }
Mady Mellor06b770c2019-08-29 18:01:00 -07006125
Colin Cross5ea7fb72019-12-18 17:16:36 -08006126 @Test
Mady Mellora7731962019-06-17 17:57:02 -07006127 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
6128 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006129 setUpPrefsForBubbles(PKG, mUid,
6130 true /* global */,
6131 BUBBLE_PREFERENCE_ALL /* app */,
6132 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006133
Mady Mellor9e923e12019-12-17 16:08:46 -08006134 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6135 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
6136 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006137 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006138 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6139 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006140
6141 // Ensure we're not foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006142 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006143 IMPORTANCE_VISIBLE);
6144
Julia Reynolds24edc002020-01-29 16:35:32 -05006145 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6146 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006147 waitForIdle();
6148
6149 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006150 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006151 assertTrue(notif.isBubbleNotification());
6152
6153 // Our flags should have failed since we're not foreground
6154 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
6155 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
6156 }
6157
6158 @Test
6159 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
6160 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006161 setUpPrefsForBubbles(PKG, mUid,
6162 true /* global */,
6163 BUBBLE_PREFERENCE_ALL /* app */,
6164 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006165
Mady Mellor9e923e12019-12-17 16:08:46 -08006166 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6167 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
6168 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006169 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006170 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6171 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006172
6173 // Ensure we are in the foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006174 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006175 IMPORTANCE_FOREGROUND);
6176
Julia Reynolds24edc002020-01-29 16:35:32 -05006177 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6178 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006179 waitForIdle();
6180
6181 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006182 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006183 assertTrue(notif.isBubbleNotification());
6184
Mady Mellor9e923e12019-12-17 16:08:46 -08006185 // Our flags should have passed since we are foreground
Mady Mellora7731962019-06-17 17:57:02 -07006186 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
6187 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
6188 }
Mady Mellor22f2f072019-04-18 13:26:18 -07006189
6190 @Test
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006191 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
6192 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006193 setUpPrefsForBubbles(PKG, mUid,
6194 true /* global */,
6195 BUBBLE_PREFERENCE_ALL /* app */,
6196 true /* channel */);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006197
6198 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6199 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6200
6201 // Messaging notification with shortcut info
6202 Notification.BubbleMetadata metadata =
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006203 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006204 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6205 null /* groupKey */, false /* isSummary */);
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006206 nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006207 nb.setBubbleMetadata(metadata);
6208 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
Julia Reynoldse61758a2020-06-10 10:26:44 -04006209 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006210 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6211
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006212 // Test: Send the bubble notification
Julia Reynolds24edc002020-01-29 16:35:32 -05006213 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6214 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006215 waitForIdle();
6216
6217 // Verify:
6218
6219 // Make sure we register the callback for shortcut changes
6220 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6221
6222 // yes allowed, yes messaging w/shortcut, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006223 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006224 assertTrue(notif.isBubbleNotification());
6225
Danning Chen28410f32020-04-21 10:28:52 -07006226 // Make sure the shortcut is cached.
6227 verify(mShortcutServiceInternal).cacheShortcuts(
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006228 anyInt(), any(), eq(PKG), eq(Collections.singletonList(VALID_CONVO_SHORTCUT_ID)),
Mehdi Alizadeha3d22ce2020-04-27 18:52:52 -07006229 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
Danning Chen28410f32020-04-21 10:28:52 -07006230
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006231 // Test: Remove the shortcut
Mady Mellor56515c42020-02-18 17:58:36 -08006232 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006233 launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04006234 UserHandle.getUserHandleForUid(mUid));
Mady Mellor56515c42020-02-18 17:58:36 -08006235 waitForIdle();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006236
6237 // Verify:
6238
6239 // Make sure callback is unregistered
6240 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6241
6242 // We're no longer a bubble
Mady Mellordb0a6022020-05-13 11:34:50 -07006243 NotificationRecord notif2 = mService.getNotificationRecord(
6244 nr.getSbn().getKey());
6245 assertNull(notif2.getShortcutInfo());
6246 assertFalse(notif2.getNotification().isBubbleNotification());
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006247 }
6248
Mady Mellor56515c42020-02-18 17:58:36 -08006249 @Test
6250 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
6251 throws RemoteException {
Danning Chen28410f32020-04-21 10:28:52 -07006252 final String shortcutId = "someshortcutId";
Mady Mellora92268c2020-03-09 17:25:08 -07006253 setUpPrefsForBubbles(PKG, mUid,
6254 true /* global */,
6255 BUBBLE_PREFERENCE_ALL /* app */,
6256 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08006257
6258 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6259 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6260
6261 // Messaging notification with shortcut info
Mady Melloraa9ce172020-03-17 10:34:20 -07006262 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
Danning Chen28410f32020-04-21 10:28:52 -07006263 shortcutId).build();
Mady Mellor56515c42020-02-18 17:58:36 -08006264 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6265 null /* groupKey */, false /* isSummary */);
Danning Chen28410f32020-04-21 10:28:52 -07006266 nb.setShortcutId(shortcutId);
Mady Mellor56515c42020-02-18 17:58:36 -08006267 nb.setBubbleMetadata(metadata);
6268 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
Julia Reynoldse61758a2020-06-10 10:26:44 -04006269 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor56515c42020-02-18 17:58:36 -08006270 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6271
6272 // Pretend the shortcut exists
6273 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
6274 ShortcutInfo info = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006275 when(info.getPackage()).thenReturn(PKG);
Danning Chen28410f32020-04-21 10:28:52 -07006276 when(info.getId()).thenReturn(shortcutId);
Danning Chen07cfaa62020-04-20 15:16:41 -07006277 when(info.getUserId()).thenReturn(USER_SYSTEM);
Mady Mellor56515c42020-02-18 17:58:36 -08006278 when(info.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006279 when(info.isEnabled()).thenReturn(true);
Mady Mellor56515c42020-02-18 17:58:36 -08006280 shortcutInfos.add(info);
6281 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006282 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6283 anyString(), anyInt(), any())).thenReturn(true);
Mady Mellor56515c42020-02-18 17:58:36 -08006284
6285 // Test: Send the bubble notification
6286 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6287 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6288 waitForIdle();
6289
6290 // Verify:
6291
6292 // Make sure we register the callback for shortcut changes
6293 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6294
6295 // yes allowed, yes messaging w/shortcut, yes bubble
6296 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6297 assertTrue(notif.isBubbleNotification());
6298
Danning Chen28410f32020-04-21 10:28:52 -07006299 // Make sure the shortcut is cached.
6300 verify(mShortcutServiceInternal).cacheShortcuts(
6301 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
Mehdi Alizadeha3d22ce2020-04-27 18:52:52 -07006302 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
Danning Chen28410f32020-04-21 10:28:52 -07006303
Mady Mellor56515c42020-02-18 17:58:36 -08006304 // Test: Remove the notification
6305 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6306 nr.getSbn().getId(), nr.getSbn().getUserId());
6307 waitForIdle();
6308
6309 // Verify:
6310
6311 // Make sure callback is unregistered
6312 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6313 }
6314
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006315 @Test
Mady Mellor22f2f072019-04-18 13:26:18 -07006316 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
6317 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006318 setUpPrefsForBubbles(PKG, mUid,
6319 true /* global */,
6320 BUBBLE_PREFERENCE_ALL /* app */,
6321 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006322
6323 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6324 true /* summaryAutoCancel */);
6325
6326 // Dismiss summary
6327 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6328 true);
Julia Reynolds24edc002020-01-29 16:35:32 -05006329 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
6330 nrSummary.getSbn().getTag(),
6331 nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
Mady Mellor22f2f072019-04-18 13:26:18 -07006332 NotificationStats.DISMISSAL_SHADE,
6333 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
6334 waitForIdle();
6335
6336 // The bubble should still exist
6337 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6338 assertEquals(1, notifsAfter.length);
6339 }
6340
6341 @Test
6342 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
6343 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006344 setUpPrefsForBubbles(PKG, mUid,
6345 true /* global */,
6346 BUBBLE_PREFERENCE_ALL /* app */,
6347 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006348
6349 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6350 true /* summaryAutoCancel */);
6351
6352 // Click summary
6353 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6354 true);
6355 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6356 nrSummary.getKey(), nv);
6357 waitForIdle();
6358
6359 // The bubble should still exist
6360 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6361 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006362
6363 // Check we got the click log and associated dismissal logs
6364 assertEquals(6, mNotificationRecordLogger.numCalls());
6365 // Skip the notification-creation logs
6366 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6367 mNotificationRecordLogger.event(3));
6368 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
6369 mNotificationRecordLogger.event(4));
6370 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
6371 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
6372 mNotificationRecordLogger.event(5));
Mady Mellor22f2f072019-04-18 13:26:18 -07006373 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04006374
6375 @Test
Beverly9e6a7642020-02-13 10:11:29 -05006376 public void testNotificationBubbles_bubbleStays_whenClicked()
6377 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006378 setUpPrefsForBubbles(PKG, mUid,
6379 true /* global */,
6380 BUBBLE_PREFERENCE_ALL /* app */,
6381 true /* channel */);
6382
Beverly9e6a7642020-02-13 10:11:29 -05006383 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
Beverly9e6a7642020-02-13 10:11:29 -05006384 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
6385 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
6386 mService.addNotification(nr);
6387
6388 // WHEN we click the notification
6389 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
6390 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6391 nr.getKey(), nv);
6392 waitForIdle();
6393
6394 // THEN the bubble should still exist
6395 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6396 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006397
6398 // Check we got the click log
6399 assertEquals(1, mNotificationRecordLogger.numCalls());
6400 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6401 mNotificationRecordLogger.event(0));
Beverly9e6a7642020-02-13 10:11:29 -05006402 }
6403
6404 @Test
Julia Reynolds57a974b2019-10-07 11:51:47 -04006405 public void testLoadDefaultApprovedServices_emptyResources() {
6406 TestableResources tr = mContext.getOrCreateTestableResources();
6407 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
6408 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
6409 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
6410 setDefaultAssistantInDeviceConfig("");
6411
6412 mService.loadDefaultApprovedServices(USER_SYSTEM);
6413
6414 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
6415 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
6416 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
6417 }
6418
6419 @Test
6420 public void testLoadDefaultApprovedServices_dnd() {
6421 TestableResources tr = mContext.getOrCreateTestableResources();
6422 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
6423 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
6424 .thenReturn(new ArraySet<>());
6425
6426 mService.loadDefaultApprovedServices(USER_SYSTEM);
6427
Jay Aliomer76e1f2722020-03-05 12:36:38 -05006428 verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
Julia Reynolds57a974b2019-10-07 11:51:47 -04006429 }
6430
6431 // TODO: add tests for the rest of the non-empty cases
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006432
6433 @Test
6434 public void testOnUnlockUser() {
6435 UserInfo ui = new UserInfo();
6436 ui.id = 10;
6437 mService.onUnlockUser(ui);
6438 waitForIdle();
6439
6440 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
6441 }
6442
6443 @Test
6444 public void testOnStopUser() {
6445 UserInfo ui = new UserInfo();
6446 ui.id = 10;
6447 mService.onStopUser(ui);
6448 waitForIdle();
6449
6450 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
6451 }
6452
6453 @Test
6454 public void testOnBootPhase() {
6455 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
6456
6457 verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
6458
6459 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
6460
6461 verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart();
6462 }
6463
6464 @Test
6465 public void testHandleOnPackageChanged() {
6466 String[] pkgs = new String[] {PKG, PKG_N_MR1};
6467 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
6468
6469 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
6470
6471 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
6472
6473 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
6474
6475 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
6476 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
6477 }
6478
6479 @Test
6480 public void testNotificationHistory_addNoisyNotification() throws Exception {
6481 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08006482 null /* tvExtender */);
Julia Reynolds24edc002020-01-29 16:35:32 -05006483 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6484 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006485 waitForIdle();
6486
6487 verify(mHistoryManager, times(1)).addNotification(any());
6488 }
Julia Reynolds0f767342019-12-18 09:11:55 -05006489
6490 @Test
6491 public void createConversationNotificationChannel() throws Exception {
6492 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
6493 original.setAllowBubbles(!original.canBubble());
6494 original.setShowBadge(!original.canShowBadge());
6495
6496 Parcel parcel = Parcel.obtain();
6497 original.writeToParcel(parcel, 0);
6498 parcel.setDataPosition(0);
6499 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
6500 assertEquals(original, orig);
6501 assertFalse(TextUtils.isEmpty(orig.getName()));
6502
6503 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6504 orig)));
6505
Julia Reynolds7c267522020-01-16 11:26:41 -05006506 mBinderService.createConversationNotificationChannelForPackage(
6507 PKG, mUid, "key", orig, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006508
6509 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006510 PKG, 0, PKG, original.getId(), false, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006511
6512 assertEquals(original.getName(), friendChannel.getName());
6513 assertEquals(original.getId(), friendChannel.getParentChannelId());
6514 assertEquals("friend", friendChannel.getConversationId());
6515 assertEquals(null, original.getConversationId());
6516 assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
Mady Mellora92268c2020-03-09 17:25:08 -07006517 assertFalse(friendChannel.canBubble()); // can't be modified by app
Julia Reynolds0f767342019-12-18 09:11:55 -05006518 assertFalse(original.getId().equals(friendChannel.getId()));
6519 assertNotNull(friendChannel.getId());
6520 }
6521
6522 @Test
6523 public void deleteConversationNotificationChannels() throws Exception {
6524 NotificationChannel messagesParent =
6525 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
6526 Parcel msgParcel = Parcel.obtain();
6527 messagesParent.writeToParcel(msgParcel, 0);
6528 msgParcel.setDataPosition(0);
6529
6530 NotificationChannel callsParent =
6531 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
6532 Parcel callParcel = Parcel.obtain();
6533 callsParent.writeToParcel(callParcel, 0);
6534 callParcel.setDataPosition(0);
6535
6536 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6537 messagesParent, callsParent)));
6538
6539 String conversationId = "friend";
6540
6541 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006542 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
6543 conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006544 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006545 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
Julia Reynolds0f767342019-12-18 09:11:55 -05006546 conversationId);
6547
6548 NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006549 PKG, 0, PKG, messagesParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006550 NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006551 PKG, 0, PKG, callsParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006552
6553 assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
6554 assertEquals(conversationId, messagesChild.getConversationId());
6555
6556 assertEquals(callsParent.getId(), callsChild.getParentChannelId());
6557 assertEquals(conversationId, callsChild.getConversationId());
6558
6559 mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
6560
6561 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006562 PKG, 0, PKG, messagesParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006563 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006564 PKG, 0, PKG, callsParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006565 }
Julia Reynolds24edc002020-01-29 16:35:32 -05006566
6567 @Test
6568 public void testCorrectCategory_systemOn_appCannotTurnOff() {
6569 int requested = 0;
6570 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6571
6572 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6573 system);
6574
6575 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
6576 }
6577
6578 @Test
6579 public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
6580 int requested = PRIORITY_CATEGORY_CALLS;
6581 int system = PRIORITY_CATEGORY_CALLS;
6582
6583 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6584 system);
6585
6586 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6587 }
6588
6589 @Test
6590 public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
6591 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6592 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6593
6594 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6595 system);
6596
6597 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
6598 }
6599
6600 @Test
6601 public void testCorrectCategory_systemOff_appCannotTurnOn() {
6602 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6603 int system = PRIORITY_CATEGORY_CALLS;
6604
6605 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6606 system);
6607
6608 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6609 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006610
6611 @Test
6612 public void testGetConversationsForPackage_hasShortcut() throws Exception {
6613 mService.setPreferencesHelper(mPreferencesHelper);
6614 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6615 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6616 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6617 channel1.setConversationId("parent1", "convo 1");
6618 convo1.setNotificationChannel(channel1);
6619 convos.add(convo1);
6620
6621 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6622 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6623 channel2.setConversationId("parent1", "convo 2");
6624 convo2.setNotificationChannel(channel2);
6625 convos.add(convo2);
6626 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6627
Julia Reynolds882f2062020-02-05 12:11:38 -05006628 ShortcutInfo si = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006629 when(si.getPackage()).thenReturn(PKG_P);
6630 when(si.getId()).thenReturn("convo");
6631 when(si.getUserId()).thenReturn(USER_SYSTEM);
Julia Reynolds8d34af82020-05-20 14:24:36 -04006632 when(si.getLabel()).thenReturn("Hello");
Mady Mellor774d5fe2020-03-05 11:35:03 -08006633 when(si.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006634 when(si.isEnabled()).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006635 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
Julia Reynoldsfa273072020-04-14 15:31:21 -04006636 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6637 anyString(), anyInt(), any())).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006638
6639 List<ConversationChannelWrapper> conversations =
6640 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6641 assertEquals(si, conversations.get(0).getShortcutInfo());
6642 assertEquals(si, conversations.get(1).getShortcutInfo());
Mady Mellor774d5fe2020-03-05 11:35:03 -08006643 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006644
Mady Mellor774d5fe2020-03-05 11:35:03 -08006645 @Test
6646 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
6647 mService.setPreferencesHelper(mPreferencesHelper);
6648 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6649 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6650 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6651 channel1.setConversationId("parent1", "convo 1");
6652 convo1.setNotificationChannel(channel1);
6653 convos.add(convo1);
6654
6655 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6656 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6657 channel2.setConversationId("parent1", "convo 2");
6658 convo2.setNotificationChannel(channel2);
6659 convos.add(convo2);
6660 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6661
6662 ShortcutInfo si = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006663 when(si.getPackage()).thenReturn(PKG_P);
6664 when(si.getId()).thenReturn("convo");
6665 when(si.getUserId()).thenReturn(USER_SYSTEM);
Julia Reynolds8d34af82020-05-20 14:24:36 -04006666 when(si.getLabel()).thenReturn("Hello");
Mady Mellor774d5fe2020-03-05 11:35:03 -08006667 when(si.isLongLived()).thenReturn(false);
6668 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6669
6670 List<ConversationChannelWrapper> conversations =
6671 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6672 assertNull(conversations.get(0).getShortcutInfo());
6673 assertNull(conversations.get(1).getShortcutInfo());
Julia Reynolds882f2062020-02-05 12:11:38 -05006674 }
6675
6676 @Test
6677 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
6678 mService.setPreferencesHelper(mPreferencesHelper);
6679 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6680 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6681 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6682 channel1.setConversationId("parent1", "convo 1");
6683 convo1.setNotificationChannel(channel1);
6684 convos.add(convo1);
6685
6686 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6687 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6688 channel2.setConversationId("parent1", "convo 2");
6689 convo2.setNotificationChannel(channel2);
6690 convos.add(convo2);
6691 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006692 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Julia Reynolds882f2062020-02-05 12:11:38 -05006693
6694 List<ConversationChannelWrapper> conversations =
6695 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6696 assertNull(conversations.get(0).getShortcutInfo());
6697 assertNull(conversations.get(1).getShortcutInfo());
6698 }
Mady Mellor57b34162020-04-01 08:44:00 -07006699
6700 @Test
6701 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
6702 mService.setShortcutHelper(null);
6703 NotificationRecord nr =
6704 generateMessageBubbleNotifRecord(mTestNotificationChannel,
6705 "testShortcutHelperNull_doesntCrashEnqueue");
6706 try {
6707 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6708 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6709 waitForIdle();
6710 } catch (Exception e) {
6711 fail(e.getMessage());
6712 }
6713 }
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006714
6715 @Test
Julia Reynolds8582df52020-04-24 18:30:59 -04006716 public void testRecordMessages_invalidMsg() throws RemoteException {
Julia Reynoldse61758a2020-06-10 10:26:44 -04006717 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6718 null /* groupKey */, false /* isSummary */);
6719 nb.setShortcutId(null);
6720 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
6721 "testRecordMessages_invalidMsg", mUid, 0, nb.build(),
6722 UserHandle.getUserHandleForUid(mUid), null, 0);
6723 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6724
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006725 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Julia Reynoldse61758a2020-06-10 10:26:44 -04006726 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006727 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6728 waitForIdle();
6729
Julia Reynoldse61758a2020-06-10 10:26:44 -04006730 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
6731 }
6732
6733 @Test
6734 public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException {
6735 Notification.Builder nb = new Notification.Builder(mContext,
6736 mTestNotificationChannel.getId())
6737 .setContentTitle("foo")
6738 .setShortcutId(null)
6739 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6740 .setCategory(Notification.CATEGORY_MESSAGE);
6741 StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1,
6742 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(),
6743 UserHandle.getUserHandleForUid(mUid), null, 0);
6744 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6745
6746 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
6747 mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(),
6748 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6749 waitForIdle();
6750
6751 // PKG_O is allowed to be in conversation space b/c of override in
6752 // TestableNotificationManagerService
6753 assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid));
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006754 }
Julia Reynolds8582df52020-04-24 18:30:59 -04006755
6756 @Test
6757 public void testRecordMessages_validMsg() throws RemoteException {
Julia Reynolds8582df52020-04-24 18:30:59 -04006758 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6759 null /* groupKey */, false /* isSummary */);
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006760 nb.setShortcutId(null);
Julia Reynoldse61758a2020-06-10 10:26:44 -04006761 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
6762 "testRecordMessages_validMsg", mUid, 0, nb.build(),
6763 UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds8582df52020-04-24 18:30:59 -04006764 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6765
Julia Reynoldse61758a2020-06-10 10:26:44 -04006766 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
Julia Reynolds8582df52020-04-24 18:30:59 -04006767 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6768 waitForIdle();
6769
Julia Reynoldse61758a2020-06-10 10:26:44 -04006770 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006771
6772 nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6773 "testRecordMessages_validMsg");
6774
Julia Reynoldse61758a2020-06-10 10:26:44 -04006775 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006776 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6777 waitForIdle();
6778
Julia Reynoldse61758a2020-06-10 10:26:44 -04006779 assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid));
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006780 }
6781
6782 @Test
6783 public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException {
6784 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6785 "testRecordMessages_invalidMsg_afterValidMsg_1");
6786 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6787 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6788 waitForIdle();
6789 assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation());
6790
6791 mBinderService.cancelAllNotifications(PKG, mUid);
6792 waitForIdle();
6793
6794 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6795 null /* groupKey */, false /* isSummary */);
6796 nb.setShortcutId(null);
6797 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
6798 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04006799 UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006800 nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6801
6802 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6803 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6804 waitForIdle();
6805
6806 assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation());
Julia Reynolds8582df52020-04-24 18:30:59 -04006807 }
Julia Reynolds1a80b292020-05-01 11:55:57 -04006808
6809 @Test
6810 public void testCanPostFgsWhenOverLimit() throws RemoteException {
6811 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
6812 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
6813 i, null, false).getSbn();
6814 mBinderService.enqueueNotificationWithTag(PKG, PKG,
6815 "testCanPostFgsWhenOverLimit",
6816 sbn.getId(), sbn.getNotification(), sbn.getUserId());
6817 }
6818
6819 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
6820 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
6821 mBinderService.enqueueNotificationWithTag(PKG, PKG,
6822 "testCanPostFgsWhenOverLimit - fgs over limit!",
6823 sbn.getId(), sbn.getNotification(), sbn.getUserId());
6824
6825 waitForIdle();
6826
6827 StatusBarNotification[] notifs =
6828 mBinderService.getActiveNotifications(sbn.getPackageName());
6829 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
6830 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
6831 mService.getNotificationRecordCount());
6832 }
6833
6834 @Test
6835 public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
6836 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
6837 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
6838 i, null, false).getSbn();
6839 mBinderService.enqueueNotificationWithTag(PKG, PKG,
6840 "testCanPostFgsWhenOverLimit",
6841 sbn.getId(), sbn.getNotification(), sbn.getUserId());
6842 waitForIdle();
6843 }
6844
6845 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
6846 100, null, false).getSbn();
6847 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
6848 mBinderService.enqueueNotificationWithTag(PKG, PKG,
6849 "testCanPostFgsWhenOverLimit - fgs over limit!",
6850 sbn.getId(), sbn.getNotification(), sbn.getUserId());
6851
6852 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
6853 101, null, false).getSbn();
6854 mBinderService.enqueueNotificationWithTag(PKG, PKG,
6855 "testCanPostFgsWhenOverLimit - non fgs over limit!",
6856 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
6857
6858 waitForIdle();
6859
6860 StatusBarNotification[] notifs =
6861 mBinderService.getActiveNotifications(sbn.getPackageName());
6862 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
6863 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
6864 mService.getNotificationRecordCount());
6865 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05006866}