blob: 62a423e327720cc233270c647a041f7c178f1fc6 [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 Reynolds2e4cb8c2021-04-05 16:58:17 -040087import android.app.AlarmManager;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -040088import android.app.AppOpsManager;
Julia Reynoldsa94365d2019-04-09 10:48:43 -040089import android.app.AutomaticZenRule;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040090import android.app.IActivityManager;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050091import android.app.INotificationManager;
Julia Reynolds268647a2018-10-25 16:54:27 -040092import android.app.ITransientNotification;
93import android.app.IUriGrantsManager;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050094import android.app.Notification;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040095import android.app.Notification.MessagingStyle.Message;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050096import android.app.NotificationChannel;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040097import android.app.NotificationChannelGroup;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050098import android.app.NotificationManager;
Mady Mellor7eb18ef2019-03-27 14:03:46 -070099import android.app.PendingIntent;
Mady Mellorbe797962019-04-01 16:04:24 -0700100import android.app.Person;
Mady Mellora10448e2019-04-26 13:50:58 -0700101import android.app.RemoteInput;
Yotam Aron74299972020-01-16 16:20:58 +0200102import android.app.StatsManager;
Jason Parks50322ff2018-03-27 10:23:33 -0500103import android.app.admin.DevicePolicyManagerInternal;
Julia Reynolds7217dc92018-03-07 12:12:09 -0500104import android.app.usage.UsageStatsManagerInternal;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400105import android.companion.ICompanionDeviceManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500106import android.content.ComponentName;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600107import android.content.ContentUris;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500108import android.content.Context;
Beverlyd4f96492017-08-02 13:36:11 -0400109import android.content.Intent;
Mady Mellora92268c2020-03-09 17:25:08 -0700110import android.content.pm.ActivityInfo;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500111import android.content.pm.ApplicationInfo;
112import android.content.pm.IPackageManager;
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800113import android.content.pm.LauncherApps;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500114import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500115import android.content.pm.ParceledListSlice;
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800116import android.content.pm.ShortcutInfo;
Julia Reynoldsfa273072020-04-14 15:31:21 -0400117import android.content.pm.ShortcutServiceInternal;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400118import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200119import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400120import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700121import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400122import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400123import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500124import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400125import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400126import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400127import android.os.IBinder;
Julia Reynolds0f767342019-12-18 09:11:55 -0500128import android.os.Parcel;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400129import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400130import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700131import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500132import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400133import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000134import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600135import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000136import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400137import android.service.notification.Adjustment;
Julia Reynolds882f2062020-02-05 12:11:38 -0500138import android.service.notification.ConversationChannelWrapper;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400139import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400140import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500141import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400142import android.service.notification.ZenPolicy;
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400143import android.telephony.TelephonyManager;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400144import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400145import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400146import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400147import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400148import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400149import android.testing.TestablePermissions;
Julia Reynolds57a974b2019-10-07 11:51:47 -0400150import android.testing.TestableResources;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400151import android.text.Html;
Julia Reynolds0f767342019-12-18 09:11:55 -0500152import android.text.TextUtils;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400153import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000154import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400155import android.util.AtomicFile;
Julia Reynolds469144c2019-06-21 14:30:28 -0400156import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400157import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400158
Mady Mellor49b1bf12019-03-29 12:00:02 -0700159import androidx.annotation.Nullable;
160import androidx.test.InstrumentationRegistry;
161
Tony Mak9a3c1f12019-03-04 16:04:42 +0000162import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Will Brockmancfd98302020-01-29 15:57:30 -0500163import com.android.internal.logging.InstanceIdSequence;
164import com.android.internal.logging.InstanceIdSequenceFake;
Julia Reynolds503ed942017-10-04 16:04:56 -0400165import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400166import com.android.internal.util.FastXmlSerializer;
Mady Mellor13f9bc82020-03-24 19:09:28 -0700167import com.android.server.DeviceIdleInternal;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700168import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400169import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500170import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400171import com.android.server.lights.LightsManager;
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100172import com.android.server.lights.LogicalLight;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400173import com.android.server.notification.NotificationManagerService.NotificationAssistants;
174import com.android.server.notification.NotificationManagerService.NotificationListeners;
Julia Reynolds2e4cb8c2021-04-05 16:58:17 -0400175import com.android.server.pm.PackageManagerService;
Bernardo Rufino18725b62020-01-21 14:12:43 +0000176import com.android.server.statusbar.StatusBarManagerInternal;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700177import com.android.server.uri.UriGrantsManagerInternal;
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000178import com.android.server.wm.ActivityTaskManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400179import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400180
Julia Reynolds59376062022-01-07 16:28:52 -0500181import com.google.common.collect.ImmutableList;
182
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400183import org.junit.After;
184import org.junit.Before;
185import org.junit.Test;
186import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500187import org.mockito.ArgumentCaptor;
188import org.mockito.Mock;
189import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400190import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400191import org.xmlpull.v1.XmlPullParser;
192import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500193
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400194import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400195import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400196import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400197import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400198import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400199import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400200import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500201import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000202import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400203import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400204import java.util.Map;
Evan Laird3f4a62d2020-08-28 11:25:04 -0400205import java.util.Set;
Julia Reynolds59376062022-01-07 16:28:52 -0500206import java.util.concurrent.CountDownLatch;
Robin Leed107af62018-04-27 13:55:56 +0200207import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500208
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400209
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400210@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400211@RunWith(AndroidTestingRunner.class)
212@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500213public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500214 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000215
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400216 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500217 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500218 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400219 private NotificationManagerInternal mInternalService;
Mady Mellor56515c42020-02-18 17:58:36 -0800220 private ShortcutHelper mShortcutHelper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400221 @Mock
222 private IPackageManager mPackageManager;
223 @Mock
224 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400225 @Mock
226 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400227 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500228 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400229 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400230 @Mock
231 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400232 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400233 AtomicFile mPolicyFile;
234 File mFile;
235 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400236 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400237 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400238 private UsageStatsManagerInternal mAppUsageStats;
239 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400240 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400241 @Mock
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800242 private LauncherApps mLauncherApps;
243 @Mock
Julia Reynoldsfa273072020-04-14 15:31:21 -0400244 private ShortcutServiceInternal mShortcutServiceInternal;
245 @Mock
Julia Reynolds68263d12017-06-21 14:21:19 -0400246 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200247 @Mock
248 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400249 @Mock
Julia Reynolds59376062022-01-07 16:28:52 -0500250 ActivityManagerInternal mAmi;
251 @Mock
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400252 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400253
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500254 private static final int MAX_POST_DELAY = 1000;
255
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500256 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500257 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000258
259 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
260
Julia Reynoldsc76888d2020-05-04 15:36:09 -0400261 private static final String VALID_CONVO_SHORTCUT_ID = "shortcut";
262
Julia Reynoldsda781472017-04-12 09:41:16 -0400263 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400264 private NotificationListeners mListeners;
265 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400266 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400267 private ManagedServices.ManagedServiceInfo mListener;
268 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400269 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400270 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400271 @Mock
272 IBinder mPermOwner;
273 @Mock
274 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700275 @Mock
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000276 ActivityTaskManagerInternal mAtm;
277 @Mock
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700278 IUriGrantsManager mUgm;
279 @Mock
280 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400281 @Mock
282 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000283 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000284 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
285 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400286 @Mock
287 UserManager mUm;
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500288 @Mock
289 NotificationHistoryManager mHistoryManager;
Yotam Aron74299972020-01-16 16:20:58 +0200290 @Mock
291 StatsManager mStatsManager;
Julia Reynolds2e4cb8c2021-04-05 16:58:17 -0400292 @Mock
293 AlarmManager mAlarmManager;
Will Brockman2b6959e2020-01-22 09:59:50 -0500294 NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
Will Brockmancfd98302020-01-29 15:57:30 -0500295 private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
296 1 << 30);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000297 @Mock
298 StatusBarManagerInternal mStatusBar;
Evan Laird3f4a62d2020-08-28 11:25:04 -0400299 private final FakeSystemClock mSystemClock = new FakeSystemClock();
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500300
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400301 // Use a Testable subclass so we can simulate calls from the system without failing.
302 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500303 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700304 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000305 int countLogSmartSuggestionsVisible = 0;
Evan Laird3f4a62d2020-08-28 11:25:04 -0400306 // If true, don't enqueue the PostNotificationRunnables, just trap them
307 boolean trapEnqueuedNotifications = false;
308 final ArrayList<NotificationManagerService.PostNotificationRunnable> trappedRunnables =
309 new ArrayList<>();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000310 @Nullable
311 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500312
Evan Laird3f4a62d2020-08-28 11:25:04 -0400313 TestableNotificationManagerService(
314 Context context,
315 NotificationRecordLogger logger,
316 InjectableSystemClock systemClock,
Will Brockmancfd98302020-01-29 15:57:30 -0500317 InstanceIdSequence notificationInstanceIdSequence) {
Evan Laird3f4a62d2020-08-28 11:25:04 -0400318 super(context, logger, systemClock, notificationInstanceIdSequence);
Amith Yamasani803eab692017-11-09 17:47:04 -0800319 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400320
Mady Mellor56515c42020-02-18 17:58:36 -0800321 RankingHelper getRankingHelper() {
322 return mRankingHelper;
323 }
324
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400325 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400326 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500327 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700328 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400329 }
330
331 @Override
332 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500333 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700334 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400335 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400336
337 @Override
338 protected ICompanionDeviceManager getCompanionManager() {
339 return null;
340 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800341
342 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800343 protected void reportUserInteraction(NotificationRecord r) {
344 return;
345 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500346
347 @Override
348 protected void handleSavePolicyFile() {
349 return;
350 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000351
352 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000353 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
354 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000355 countLogSmartSuggestionsVisible++;
356 }
357
Annie Meng8b646fd2019-02-01 18:46:42 +0000358 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000359 protected void setNotificationAssistantAccessGrantedForUserInternal(
360 ComponentName assistant, int userId, boolean granted) {
361 if (mNotificationAssistantAccessGrantedCallback != null) {
362 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
363 return;
364 }
365 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
366 }
367
Julia Reynoldse61758a2020-06-10 10:26:44 -0400368 @Override
369 protected String[] getStringArrayResource(int key) {
370 return new String[] {PKG_O};
371 }
372
Evan Laird3f4a62d2020-08-28 11:25:04 -0400373 @Override
374 protected void postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record,
375 PostNotificationRunnable runnable) {
376 if (trapEnqueuedNotifications) {
377 trappedRunnables.add(runnable);
378 return;
379 }
380
381 super.postPostNotificationRunnableMaybeDelayedLocked(record, runnable);
382 }
383
384 void drainTrappedRunnableQueue() {
385 for (Runnable r : trappedRunnables) {
386 getWorkHandler().post(r);
387 }
388 }
389
Tony Mak9a3c1f12019-03-04 16:04:42 +0000390 private void setNotificationAssistantAccessGrantedCallback(
391 @Nullable NotificationAssistantAccessGrantedCallback callback) {
392 this.mNotificationAssistantAccessGrantedCallback = callback;
393 }
394
395 interface NotificationAssistantAccessGrantedCallback {
396 void onGranted(ComponentName assistant, int userId, boolean granted);
397 }
Mady Mellor56515c42020-02-18 17:58:36 -0800398 }
399
Beverly58b24532018-10-02 09:08:23 -0400400 private class TestableToastCallback extends ITransientNotification.Stub {
401 @Override
402 public void show(IBinder windowToken) {
403 }
404
405 @Override
406 public void hide() {
407 }
408 }
409
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500410 @Before
411 public void setUp() throws Exception {
Beverly24d103b2020-02-18 17:40:57 -0500412 // Shell permisssions will override permissions of our app, so add all necessary permissions
Beverly080782f2020-02-24 16:42:57 -0500413 // for this test here:
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000414 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Beverly24d103b2020-02-18 17:40:57 -0500415 "android.permission.WRITE_DEVICE_CONFIG",
416 "android.permission.READ_DEVICE_CONFIG",
417 "android.permission.READ_CONTACTS");
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000418
Julia Reynoldsda781472017-04-12 09:41:16 -0400419 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400420
Mady Mellor13f9bc82020-03-24 19:09:28 -0700421 DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
422 when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
Mady Mellor13f9bc82020-03-24 19:09:28 -0700423
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700424 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
425 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400426 LocalServices.removeServiceForTest(WindowManagerInternal.class);
427 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Bernardo Rufino18725b62020-01-21 14:12:43 +0000428 LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
429 LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
Mady Mellor13f9bc82020-03-24 19:09:28 -0700430 LocalServices.removeServiceForTest(DeviceIdleInternal.class);
431 LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
432 LocalServices.removeServiceForTest(ActivityManagerInternal.class);
Julia Reynolds59376062022-01-07 16:28:52 -0500433 LocalServices.addService(ActivityManagerInternal.class, mAmi);
Julia Reynolds2e4cb8c2021-04-05 16:58:17 -0400434 mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
435
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700436
Julia Reynolds4afe2642019-05-01 08:42:24 -0400437 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
438
Will Brockmancfd98302020-01-29 15:57:30 -0500439 mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
Evan Laird3f4a62d2020-08-28 11:25:04 -0400440 mSystemClock, mNotificationInstanceIdSequence);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500441
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400442 // Use this testable looper.
443 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500444 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400445 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400446
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400447 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400448 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
449 Object[] args = invocation.getArguments();
450 return getApplicationInfo((String) args[0], mUid);
451 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500452 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400453 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
454 Object[] args = invocation.getArguments();
455 return getApplicationInfo((String) args[0], mUid);
456 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400457 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500458 final LightsManager mockLightsManager = mock(LightsManager.class);
Ivailo Karamanolevf773e102020-01-16 16:10:42 +0100459 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400460 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400461 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700462 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400463 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400464 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400465 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Julia Reynolds8613ca32022-02-11 17:08:58 -0500466 when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500467
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400468 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400469 mFile = new File(mContext.getCacheDir(), "test.xml");
470 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400471 final String preupgradeXml = "<notification-policy></notification-policy>";
472 mPolicyFile = new AtomicFile(mFile);
473 FileOutputStream fos = mPolicyFile.startWrite();
474 fos.write(preupgradeXml.getBytes());
475 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400476
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400477 // Setup managed services
478 mListener = mListeners.new ManagedServiceInfo(
Julia Reynoldse61758a2020-06-10 10:26:44 -0400479 null, new ComponentName(PKG, "test_class"),
480 UserHandle.getUserId(mUid), true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400481 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
482 ArraySet<ComponentName> components = new ArraySet<>();
483 components.add(defaultComponent);
484 when(mListeners.getDefaultComponents()).thenReturn(components);
485 when(mConditionProviders.getDefaultPackages())
486 .thenReturn(new ArraySet<>(Arrays.asList("config")));
487 when(mAssistants.getDefaultComponents()).thenReturn(components);
488 when(mAssistants.queryPackageForServices(
489 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldse61758a2020-06-10 10:26:44 -0400490 when(mListeners.checkServiceTokenLocked(null)).thenReturn(mListener);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400491 ManagedServices.Config listenerConfig = new ManagedServices.Config();
492 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
493 when(mListeners.getConfig()).thenReturn(listenerConfig);
494 ManagedServices.Config assistantConfig = new ManagedServices.Config();
495 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
496 when(mAssistants.getConfig()).thenReturn(assistantConfig);
497 ManagedServices.Config dndConfig = new ManagedServices.Config();
498 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
499 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
500
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400501 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
502
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500503 mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
504 mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400505 mListeners, mAssistants, mConditionProviders,
506 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +0000507 mGroupHelper, mAm, mAtm, mAppUsageStats,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400508 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
Will Brockmanaf25fbd2020-03-26 15:49:47 -0400509 mAppOpsManager, mUm, mHistoryManager, mStatsManager,
Christopher Tate9b67d752020-11-18 17:22:45 -0800510 mock(TelephonyManager.class),
Julia Reynolds59376062022-01-07 16:28:52 -0500511 mAmi);
Julia Reynolds4afe2642019-05-01 08:42:24 -0400512 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
513
Julia Reynolds503ed942017-10-04 16:04:56 -0400514 mService.setAudioManager(mAudioManager);
Mady Mellor56515c42020-02-18 17:58:36 -0800515
516 mShortcutHelper = mService.getShortcutHelper();
517 mShortcutHelper.setLauncherApps(mLauncherApps);
Julia Reynoldsfa273072020-04-14 15:31:21 -0400518 mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
Mady Mellor56515c42020-02-18 17:58:36 -0800519
Julia Reynoldsc76888d2020-05-04 15:36:09 -0400520 // Pretend the shortcut exists
521 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
522 ShortcutInfo info = mock(ShortcutInfo.class);
523 when(info.getPackage()).thenReturn(PKG);
524 when(info.getId()).thenReturn(VALID_CONVO_SHORTCUT_ID);
525 when(info.getUserId()).thenReturn(USER_SYSTEM);
526 when(info.isLongLived()).thenReturn(true);
527 when(info.isEnabled()).thenReturn(true);
528 shortcutInfos.add(info);
529 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
530 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
531 anyString(), anyInt(), any())).thenReturn(true);
532
Mady Mellor56515c42020-02-18 17:58:36 -0800533 // Set the testable bubble extractor
534 RankingHelper rankingHelper = mService.getRankingHelper();
535 BubbleExtractor extractor = rankingHelper.findExtractor(BubbleExtractor.class);
Mady Mellora92268c2020-03-09 17:25:08 -0700536 extractor.setActivityManager(mActivityManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500537
538 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400539 mBinderService = mService.getBinderService();
540 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500541
542 mBinderService.createNotificationChannels(
543 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldse61758a2020-06-10 10:26:44 -0400544 mBinderService.createNotificationChannels(
545 PKG_P, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
546 mBinderService.createNotificationChannels(
547 PKG_O, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400548 assertNotNull(mBinderService.getNotificationChannel(
549 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400550 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500551 }
552
Julia Reynoldsb852e562017-06-06 16:14:18 -0400553 @After
Will Brockman9918db92020-03-06 16:48:39 -0500554 public void assertNotificationRecordLoggerCallsValid() {
555 for (NotificationRecordLoggerFake.CallRecord call : mNotificationRecordLogger.getCalls()) {
556 if (call.wasLogged) {
557 assertNotNull(call.event);
558 }
559 }
560 }
561
562 @After
Julia Reynoldsb852e562017-06-06 16:14:18 -0400563 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400564 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000565 clearDeviceConfig();
Julia Reynoldsb317ff72019-11-26 14:20:51 -0500566 mService.unregisterDeviceConfigChange();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000567 InstrumentationRegistry.getInstrumentation()
568 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400569 }
570
Jay Aliomer4204f252019-08-26 11:36:53 -0400571 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
572 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
573 changed.put(true, new ArrayList<>());
574 changed.put(false, new ArrayList<>());
575 return changed;
576 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400577 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
578 final ApplicationInfo applicationInfo = new ApplicationInfo();
579 applicationInfo.uid = uid;
580 switch (pkg) {
581 case PKG_N_MR1:
582 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
583 break;
584 case PKG_O:
585 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
586 break;
587 case PKG_P:
588 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
589 break;
590 default:
591 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
592 break;
593 }
594 return applicationInfo;
595 }
596
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500597 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400598 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500599 }
600
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500601 private void setUpPrefsForBubbles(String pkg, int uid, boolean globalEnabled,
Mady Mellora92268c2020-03-09 17:25:08 -0700602 int pkgPref, boolean channelEnabled) {
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500603 Settings.Global.putInt(mContext.getContentResolver(),
604 Settings.Global.NOTIFICATION_BUBBLES, globalEnabled ? 1 : 0);
605 mService.mPreferencesHelper.updateBubblesEnabled();
606 assertEquals(globalEnabled, mService.mPreferencesHelper.bubblesEnabled());
607 try {
Mady Mellora92268c2020-03-09 17:25:08 -0700608 mBinderService.setBubblesAllowed(pkg, uid, pkgPref);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -0500609 } catch (RemoteException e) {
610 e.printStackTrace();
611 }
Mady Mellorc6820342019-05-20 12:04:36 -0700612 mTestNotificationChannel.setAllowBubbles(channelEnabled);
613 }
614
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500615 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
616 Notification.Builder nb = new Notification.Builder(mContext, "a")
617 .setContentTitle("foo")
618 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400619 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
620 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500621 nb.build(), new UserHandle(userId), null, postTime);
622 return sbn;
623 }
624
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400625 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
626 String groupKey, boolean isSummary) {
627 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
628 .setContentTitle("foo")
629 .setSmallIcon(android.R.drawable.sym_def_app_icon)
630 .setGroup(groupKey)
631 .setGroupSummary(isSummary);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400632 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
633 "tag" + System.currentTimeMillis(), mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -0400634 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000635 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400636 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400637
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500638 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500639 return generateNotificationRecord(channel, null);
640 }
641
642 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
643 Notification.TvExtender extender) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500644 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500645 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500646 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500647 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500648 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500649 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500650 if (extender != null) {
651 nb.extend(extender);
652 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400653 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -0400654 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000655 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500656 }
657
Aran Inkfd2bfd32019-10-04 16:30:01 -0400658 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
659 if (channel == null) {
660 channel = mTestNotificationChannel;
661 }
662 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
663 .setContentTitle("foo")
664 .setSmallIcon(android.R.drawable.sym_def_app_icon);
665 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
666 nb.build(), new UserHandle(userId), null, 0);
667 return new NotificationRecord(mContext, sbn, channel);
668 }
669
Mady Mellor9e923e12019-12-17 16:08:46 -0800670 private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
671 String tag) {
672 return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
673 }
674
675 private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
676 NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
677 if (channel == null) {
678 channel = mTestNotificationChannel;
679 }
680 if (tag == null) {
681 tag = "tag";
682 }
683 Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
684 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
685 tag, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -0400686 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor9e923e12019-12-17 16:08:46 -0800687 return new NotificationRecord(mContext, sbn, channel);
688 }
689
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400690 private Map<String, Answer> getSignalExtractorSideEffects() {
691 Map<String, Answer> answers = new ArrayMap<>();
692
693 answers.put("override group key", invocationOnMock -> {
694 ((NotificationRecord) invocationOnMock.getArguments()[0])
695 .setOverrideGroupKey("bananas");
696 return null;
697 });
698 answers.put("override people", invocationOnMock -> {
699 ((NotificationRecord) invocationOnMock.getArguments()[0])
700 .setPeopleOverride(new ArrayList<>());
701 return null;
702 });
703 answers.put("snooze criteria", invocationOnMock -> {
704 ((NotificationRecord) invocationOnMock.getArguments()[0])
705 .setSnoozeCriteria(new ArrayList<>());
706 return null;
707 });
708 answers.put("notification channel", invocationOnMock -> {
709 ((NotificationRecord) invocationOnMock.getArguments()[0])
710 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
711 return null;
712 });
713 answers.put("badging", invocationOnMock -> {
714 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
715 r.setShowBadge(!r.canShowBadge());
716 return null;
717 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500718 answers.put("bubbles", invocationOnMock -> {
719 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
720 r.setAllowBubble(!r.canBubble());
721 return null;
722 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400723 answers.put("package visibility", invocationOnMock -> {
724 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
725 Notification.VISIBILITY_SECRET);
726 return null;
727 });
728
729 return answers;
730 }
731
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400732 private void clearDeviceConfig() {
733 DeviceConfig.resetToDefaults(
734 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
735 }
736
737 private void setDefaultAssistantInDeviceConfig(String componentName) {
738 DeviceConfig.setProperty(
739 DeviceConfig.NAMESPACE_SYSTEMUI,
740 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
741 componentName,
742 false);
743 }
744
Mady Mellor9e923e12019-12-17 16:08:46 -0800745 private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
746 String groupKey, boolean isSummary) {
747 // Give it a person
748 Person person = new Person.Builder()
749 .setName("bubblebot")
750 .build();
Mady Mellor9e923e12019-12-17 16:08:46 -0800751 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
752 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
753 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
754 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
755 inputIntent).addRemoteInput(remoteInput)
756 .build();
757 // Make it messaging style
758 Notification.Builder nb = new Notification.Builder(mContext,
759 mTestNotificationChannel.getId())
760 .setContentTitle("foo")
761 .setStyle(new Notification.MessagingStyle(person)
762 .setConversationTitle("Bubble Chat")
763 .addMessage("Hello?",
764 SystemClock.currentThreadTimeMillis() - 300000, person)
765 .addMessage("Is it me you're looking for?",
766 SystemClock.currentThreadTimeMillis(), person)
767 )
768 .setActions(replyAction)
769 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldsc76888d2020-05-04 15:36:09 -0400770 .setShortcutId(VALID_CONVO_SHORTCUT_ID)
Mady Mellor9e923e12019-12-17 16:08:46 -0800771 .setGroupSummary(isSummary);
772 if (groupKey != null) {
773 nb.setGroup(groupKey);
774 }
775 if (addBubbleMetadata) {
Mady Mellora92268c2020-03-09 17:25:08 -0700776 nb.setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -0800777 }
778 return nb;
779 }
780
Mady Mellora92268c2020-03-09 17:25:08 -0700781 private Notification.BubbleMetadata getBubbleMetadata() {
782 PendingIntent pendingIntent = mock(PendingIntent.class);
783 Intent intent = mock(Intent.class);
784 when(pendingIntent.getIntent()).thenReturn(intent);
785
786 ActivityInfo info = new ActivityInfo();
787 info.resizeMode = RESIZE_MODE_RESIZEABLE;
788 when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
789
790 return new Notification.BubbleMetadata.Builder(
791 pendingIntent,
792 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
793 .build();
794 }
795
Mady Mellor22f2f072019-04-18 13:26:18 -0700796 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
797 throws RemoteException {
798
Mady Mellor9e923e12019-12-17 16:08:46 -0800799 String groupKey = "BUBBLE_GROUP";
Mady Mellor22f2f072019-04-18 13:26:18 -0700800
Mady Mellor9e923e12019-12-17 16:08:46 -0800801 // Notification that has bubble metadata
802 NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
803 mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
Mady Mellor22f2f072019-04-18 13:26:18 -0700804
Julia Reynolds24edc002020-01-29 16:35:32 -0500805 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.getSbn().getTag(),
806 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
807 nrBubble.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700808 waitForIdle();
809
810 // Make sure we are a bubble
811 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
812 assertEquals(1, notifsAfter.length);
813 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
814
Mady Mellor9e923e12019-12-17 16:08:46 -0800815 // Notification without bubble metadata
816 NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
817 mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
818
Julia Reynolds24edc002020-01-29 16:35:32 -0500819 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.getSbn().getTag(),
820 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
821 nrPlain.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700822 waitForIdle();
823
824 notifsAfter = mBinderService.getActiveNotifications(PKG);
825 assertEquals(2, notifsAfter.length);
826
827 // Summary notification for both of those
Mady Mellor9e923e12019-12-17 16:08:46 -0800828 NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
829 mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
830
Mady Mellor22f2f072019-04-18 13:26:18 -0700831 if (summaryAutoCancel) {
832 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
833 }
Julia Reynolds24edc002020-01-29 16:35:32 -0500834 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.getSbn().getTag(),
835 nrSummary.getSbn().getId(), nrSummary.getSbn().getNotification(),
836 nrSummary.getSbn().getUserId());
Mady Mellor22f2f072019-04-18 13:26:18 -0700837 waitForIdle();
838
839 notifsAfter = mBinderService.getActiveNotifications(PKG);
840 assertEquals(3, notifsAfter.length);
841
842 return nrSummary;
843 }
844
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500845 @Test
Julia Reynolds2e4cb8c2021-04-05 16:58:17 -0400846 public void testLimitTimeOutBroadcast() {
847 NotificationChannel channel = new NotificationChannel("id", "name",
848 NotificationManager.IMPORTANCE_HIGH);
849 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
850 .setContentTitle("foo")
851 .setSmallIcon(android.R.drawable.sym_def_app_icon)
852 .setTimeoutAfter(1);
853
854 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
855 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
856 NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
857
858 mService.scheduleTimeoutLocked(r);
859 ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
860 verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
861 assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
862 captor.getValue().getIntent().getPackage());
863 }
864
865 @Test
Jay Aliomerfea80252019-11-20 18:14:24 -0500866 public void testDefaultAssistant_overrideDefault() {
867 final int userId = 0;
868 final String testComponent = "package/class";
869 final List<UserInfo> userInfos = new ArrayList<>();
870 userInfos.add(new UserInfo(0, "", 0));
871 final ArraySet<ComponentName> validAssistants = new ArraySet<>();
872 validAssistants.add(ComponentName.unflattenFromString(testComponent));
Jay Aliomerfea80252019-11-20 18:14:24 -0500873 when(mActivityManager.isLowRamDevice()).thenReturn(false);
874 when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
875 .thenReturn(validAssistants);
Jay Aliomer76e1f2722020-03-05 12:36:38 -0500876 when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
Jay Aliomerfea80252019-11-20 18:14:24 -0500877 when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
878
879 mService.setDefaultAssistantForUser(userId);
880
881 verify(mAssistants).setPackageOrComponentEnabled(
882 eq(testComponent), eq(userId), eq(true), eq(true));
Jay Aliomerfea80252019-11-20 18:14:24 -0500883 }
884
885 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500886 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500887 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500888 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400889 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500890 new ParceledListSlice(Arrays.asList(channel)));
891 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400892 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500893 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500894 }
895
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500896 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500897 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500898 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400899 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200900 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500901 fail("Exception should be thrown immediately.");
902 } catch (NullPointerException e) {
903 // pass
904 }
905 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500906
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500907 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500908 public void testCreateNotificationChannels_TwoChannels() throws Exception {
909 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500910 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500911 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500912 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400913 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500914 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400915 assertTrue(mBinderService.getNotificationChannel(
916 PKG, mContext.getUserId(), PKG, "id1") != null);
917 assertTrue(mBinderService.getNotificationChannel(
918 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500919 }
920
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500921 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400922 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
923 throws Exception {
924 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500925 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400926 mBinderService.createNotificationChannels(PKG,
927 new ParceledListSlice(Arrays.asList(channel)));
928
929 // Recreating the channel doesn't throw, but ignores importance.
930 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400931 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400932 mBinderService.createNotificationChannels(PKG,
933 new ParceledListSlice(Arrays.asList(dupeChannel)));
934 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400935 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500936 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400937 }
938
939 @Test
940 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
941 throws Exception {
942 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500943 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400944 mBinderService.createNotificationChannels(PKG,
945 new ParceledListSlice(Arrays.asList(channel)));
946
947 // Recreating with a lower importance is allowed to modify the channel.
948 final NotificationChannel dupeChannel =
949 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
950 mBinderService.createNotificationChannels(PKG,
951 new ParceledListSlice(Arrays.asList(dupeChannel)));
952 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400953 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400954 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
955 }
956
957 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400958 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
959 throws Exception {
960 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500961 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400962 mBinderService.createNotificationChannels(PKG,
963 new ParceledListSlice(Arrays.asList(channel)));
964
965 // The user modifies importance directly, can no longer be changed by the app.
966 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400967 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400968 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
969
970 // Recreating with a lower importance leaves channel unchanged.
971 final NotificationChannel dupeChannel =
972 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
973 mBinderService.createNotificationChannels(PKG,
974 new ParceledListSlice(Arrays.asList(dupeChannel)));
975 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400976 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400977 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400978 }
979
980 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500981 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
982 throws Exception {
983 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500984 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500985 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400986 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400987 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500988 new ParceledListSlice(Arrays.asList(channel1, channel2)));
989 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400990 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500991 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500992 }
993
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500994 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500995 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500996 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
997
998 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400999 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001000 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -04001001
1002 // isBlocked is only used for user blocking, not app suspension
1003 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001004 }
1005
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001006 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001007 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001008 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1009
1010 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001011 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001012 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -04001013 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -04001014 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001015
1016 mBinderService.createNotificationChannels(
1017 PKG, new ParceledListSlice(Arrays.asList(channel)));
Julia Reynolds24edc002020-01-29 16:35:32 -05001018 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001019 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1020 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001021 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1022 waitForIdle();
1023 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1024 }
1025
1026 @Test
1027 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
1028 throws Exception {
1029 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1030
1031 NotificationChannel channel = new NotificationChannel("blocked", "name",
1032 NotificationManager.IMPORTANCE_NONE);
1033 mBinderService.createNotificationChannels(
1034 PKG, new ParceledListSlice(Arrays.asList(channel)));
1035
Julia Reynolds24edc002020-01-29 16:35:32 -05001036 final StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001037 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001038 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001039 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1040 waitForIdle();
1041 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1042 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04001043 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001044 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1045 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001046 }
1047
1048 @Test
1049 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
1050 throws Exception {
1051 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1052
1053 NotificationChannel channel =
1054 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
1055 mBinderService.createNotificationChannels(
1056 PKG, new ParceledListSlice(Arrays.asList(channel)));
1057
1058 NotificationChannel update =
1059 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1060 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1061 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001062 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1063 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001064
Julia Reynolds24edc002020-01-29 16:35:32 -05001065 StatusBarNotification sbn = generateNotificationRecord(channel).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001066 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001067 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001068 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1069 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001070 // The first time a foreground service notification is shown, we allow the channel
1071 // to be updated to allow it to be seen.
1072 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
1073 assertEquals(IMPORTANCE_LOW,
1074 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001075 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
1076 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -04001077 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001078 waitForIdle();
1079
1080 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
1081 update.setFgServiceShown(true);
1082 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
1083 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001084 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1085 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001086
Julia Reynolds24edc002020-01-29 16:35:32 -05001087 sbn = generateNotificationRecord(channel).getSbn();
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001088 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001089 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1090 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -07001091 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1092 waitForIdle();
1093 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001094 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001095 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04001096 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
1097 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001098 }
1099
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001100 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -04001101 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
1102 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001103 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001104 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
1105 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -04001106
1107 NotificationChannel channel = new NotificationChannel("id", "name",
1108 NotificationManager.IMPORTANCE_HIGH);
1109 channel.setGroup("something");
1110 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -04001111 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -04001112 verify(mUsageStats, times(1)).registerBlocked(eq(r));
1113 }
1114
1115 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -04001116 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001117 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1118
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001119 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -04001120
Julia Reynolds24edc002020-01-29 16:35:32 -05001121 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001122 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1123 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -04001124 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1125 waitForIdle();
1126 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -05001127 }
1128
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001129 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001130 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
1131 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
1132
1133 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
1134
Julia Reynolds24edc002020-01-29 16:35:32 -05001135 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001136 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001137 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1138 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001139 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1140 waitForIdle();
1141 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001142 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001143 }
1144
Brad Stenning8c991ea2018-07-31 13:33:01 -07001145 /**
1146 * Confirm the system user on automotive devices can use car categories
1147 */
1148 @Test
1149 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
1150 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1151 .thenReturn(true);
1152 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1153 Notification.CATEGORY_CAR_WARNING,
1154 Notification.CATEGORY_CAR_INFORMATION);
1155 int id = 0;
1156 for (String category: categories) {
1157 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001158 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001159 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001160 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1161 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001162 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1163 }
1164 waitForIdle();
1165 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1166 }
1167
1168
1169 /**
1170 * Confirm restricted notification categories only apply to automotive.
1171 */
1172 @Test
1173 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
1174 mService.isSystemUid = false;
1175 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1176 .thenReturn(false);
1177 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1178 Notification.CATEGORY_CAR_WARNING,
1179 Notification.CATEGORY_CAR_INFORMATION);
1180 int id = 0;
1181 for (String category: categories) {
1182 final StatusBarNotification sbn =
Julia Reynolds24edc002020-01-29 16:35:32 -05001183 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001184 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001185 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1186 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001187 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1188 }
1189 waitForIdle();
1190 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
1191 }
1192
1193 /**
1194 * Confirm if a non-system user tries to use the car categories on a automotive device that
1195 * they will get a security exception
1196 */
1197 @Test
1198 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
1199 mService.isSystemUid = false;
1200 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
1201 .thenReturn(true);
1202 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
1203 Notification.CATEGORY_CAR_WARNING,
1204 Notification.CATEGORY_CAR_INFORMATION);
1205 for (String category: categories) {
Julia Reynolds24edc002020-01-29 16:35:32 -05001206 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Brad Stenning8c991ea2018-07-31 13:33:01 -07001207 sbn.getNotification().category = category;
1208 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001209 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1210 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -07001211 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1212 fail("Calls from non system apps should not allow use of restricted categories");
1213 } catch (SecurityException e) {
1214 // pass
1215 }
1216 }
1217 waitForIdle();
1218 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
1219 }
1220
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001221 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001222 public void testBlockedNotifications_blockedByAssistant() throws Exception {
1223 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001224 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001225
1226 NotificationChannel channel = new NotificationChannel("id", "name",
1227 NotificationManager.IMPORTANCE_HIGH);
1228 NotificationRecord r = generateNotificationRecord(channel);
1229 mService.addEnqueuedNotification(r);
1230
Julia Reynolds27c0a962018-12-10 12:37:28 -05001231 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001232 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001233 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05001234 r.getSbn().getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05001235 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001236
1237 NotificationManagerService.PostNotificationRunnable runnable =
1238 mService.new PostNotificationRunnable(r.getKey());
1239 runnable.run();
1240 waitForIdle();
1241
1242 verify(mUsageStats, never()).registerPostedByApp(any());
1243 }
1244
1245 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001246 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001247 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1248 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001249 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001250 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001251 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001252 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001253 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001254 }
1255
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001256 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001257 public void testEnqueueNotificationWithTag_WritesExpectedLogs() throws Exception {
Will Brockman2b6959e2020-01-22 09:59:50 -05001258 final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
1259 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1260 generateNotificationRecord(null).getNotification(), 0);
1261 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001262 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001263
Will Brockman2b6959e2020-01-22 09:59:50 -05001264 NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
Will Brockman9918db92020-03-06 16:48:39 -05001265 assertTrue(call.wasLogged);
Will Brockman75c60572020-01-31 10:30:27 -05001266 assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
1267 call.event);
Will Brockman2b6959e2020-01-22 09:59:50 -05001268 assertNotNull(call.r);
1269 assertNull(call.old);
1270 assertEquals(0, call.position);
1271 assertEquals(0, call.buzzBeepBlink);
Julia Reynolds24edc002020-01-29 16:35:32 -05001272 assertEquals(PKG, call.r.getSbn().getPackageName());
1273 assertEquals(0, call.r.getSbn().getId());
1274 assertEquals(tag, call.r.getSbn().getTag());
Will Brockman4f0f9d22020-02-23 21:18:11 -05001275 assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order
Will Brockman2b6959e2020-01-22 09:59:50 -05001276 }
1277
1278 @Test
1279 public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
1280 final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
1281 Notification original = new Notification.Builder(mContext,
1282 mTestNotificationChannel.getId())
1283 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1284 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
1285 Notification update = new Notification.Builder(mContext,
1286 mTestNotificationChannel.getId())
1287 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1288 .setCategory(Notification.CATEGORY_ALARM).build();
1289 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
1290 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001291 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001292
Will Brockman9918db92020-03-06 16:48:39 -05001293 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001294 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001295 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001296 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001297 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001298
Will Brockman9918db92020-03-06 16:48:39 -05001299 assertTrue(mNotificationRecordLogger.get(1).wasLogged);
Will Brockman2b6959e2020-01-22 09:59:50 -05001300 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001301 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED,
Will Brockman9918db92020-03-06 16:48:39 -05001302 mNotificationRecordLogger.event(1));
Will Brockmancfd98302020-01-29 15:57:30 -05001303 // Instance ID doesn't change on update of an active notification
Will Brockman4f0f9d22020-02-23 21:18:11 -05001304 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman2b6959e2020-01-22 09:59:50 -05001305 }
1306
1307 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05001308 public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate() throws Exception {
1309 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdate";
Will Brockman2b6959e2020-01-22 09:59:50 -05001310 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1311 generateNotificationRecord(null).getNotification(), 0);
1312 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1313 generateNotificationRecord(null).getNotification(), 0);
1314 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001315 assertEquals(2, mNotificationRecordLogger.numCalls());
1316 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockmand3d49332020-02-10 19:43:03 -05001317 assertEquals(
1318 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001319 mNotificationRecordLogger.event(0));
1320 assertFalse(mNotificationRecordLogger.get(1).wasLogged);
1321 assertNull(mNotificationRecordLogger.event(1));
Will Brockmand3d49332020-02-10 19:43:03 -05001322 }
1323
1324 @Test
1325 public void testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate() throws Exception {
1326 final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnTitleUpdate";
1327 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
1328 generateNotificationRecord(null).getNotification(),
1329 0);
1330 final Notification notif = generateNotificationRecord(null).getNotification();
1331 notif.extras.putString(Notification.EXTRA_TITLE, "Changed title");
1332 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notif, 0);
1333 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001334 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05001335 assertEquals(
1336 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001337 mNotificationRecordLogger.event(0));
1338 assertNull(mNotificationRecordLogger.event(1));
Will Brockman2b6959e2020-01-22 09:59:50 -05001339 }
1340
1341 @Test
Will Brockmancfd98302020-01-29 15:57:30 -05001342 public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception {
1343 final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel";
1344 Notification notification = new Notification.Builder(mContext,
1345 mTestNotificationChannel.getId())
1346 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
1347 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1348 waitForIdle();
1349 mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0);
1350 waitForIdle();
1351 mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
1352 waitForIdle();
Will Brockman9918db92020-03-06 16:48:39 -05001353 assertEquals(3, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001354
Will Brockmancfd98302020-01-29 15:57:30 -05001355 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001356 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001357 mNotificationRecordLogger.event(0));
1358 assertTrue(mNotificationRecordLogger.get(0).wasLogged);
Will Brockman4f0f9d22020-02-23 21:18:11 -05001359 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmancfd98302020-01-29 15:57:30 -05001360
Will Brockmancfd98302020-01-29 15:57:30 -05001361 assertEquals(
Will Brockman75c60572020-01-31 10:30:27 -05001362 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
Will Brockman9918db92020-03-06 16:48:39 -05001363 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05001364 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001365
1366 assertEquals(
1367 NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
Will Brockman9918db92020-03-06 16:48:39 -05001368 mNotificationRecordLogger.event(2));
1369 assertTrue(mNotificationRecordLogger.get(2).wasLogged);
Will Brockmancfd98302020-01-29 15:57:30 -05001370 // New instance ID because notification was canceled before re-post
Will Brockman4f0f9d22020-02-23 21:18:11 -05001371 assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId());
Will Brockman75c60572020-01-31 10:30:27 -05001372 }
1373
1374 @Test
1375 public void testCancelNonexistentNotification() throws Exception {
1376 mBinderService.cancelNotificationWithTag(PKG, PKG,
1377 "testCancelNonexistentNotification", 0, 0);
1378 waitForIdle();
1379 // The notification record logger doesn't even get called when a nonexistent notification
1380 // is cancelled, because that happens very frequently and is not interesting.
Will Brockman9918db92020-03-06 16:48:39 -05001381 assertEquals(0, mNotificationRecordLogger.numCalls());
Will Brockmancfd98302020-01-29 15:57:30 -05001382 }
1383
1384 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001385 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001386 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1387 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001388 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001389 mBinderService.cancelNotificationWithTag(PKG, PKG,
1390 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001391 waitForIdle();
1392 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001393 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001394 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001395 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001396 }
1397
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001398 @Test
Evan Lairdd04af512020-01-09 11:18:09 -05001399 public void testPostCancelPostNotifiesListeners() throws Exception {
1400 // WHEN a notification is posted
1401 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1402 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1403 sbn.getNotification(), sbn.getUserId());
Evan Laird3f4a62d2020-08-28 11:25:04 -04001404 mSystemClock.advanceTime(1);
Evan Lairdd04af512020-01-09 11:18:09 -05001405 // THEN it is canceled
1406 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Evan Laird3f4a62d2020-08-28 11:25:04 -04001407 mSystemClock.advanceTime(1);
Evan Lairdd04af512020-01-09 11:18:09 -05001408 // THEN it is posted again (before the cancel has a chance to finish)
1409 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1410 sbn.getNotification(), sbn.getUserId());
1411 // THEN the later enqueue isn't swallowed by the cancel. I.e., ordering is respected
1412 waitForIdle();
1413
1414 // The final enqueue made it to the listener instead of being canceled
1415 StatusBarNotification[] notifs =
1416 mBinderService.getActiveNotifications(PKG);
1417 assertEquals(1, notifs.length);
1418 assertEquals(1, mService.getNotificationRecordCount());
1419 }
1420
1421 @Test
Evan Laird3f4a62d2020-08-28 11:25:04 -04001422 public void testChangeSystemTimeAfterPost_thenCancel_noFgs() throws Exception {
1423 // GIVEN time X
1424 mSystemClock.setCurrentTimeMillis(10000);
1425
1426 // GIVEN a notification is posted
1427 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1428 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1429 sbn.getNotification(), sbn.getUserId());
1430 mSystemClock.advanceTime(1);
1431 waitForIdle();
1432
1433 // THEN the system time is changed to an earlier time
1434 mSystemClock.setCurrentTimeMillis(5000);
1435
1436 // THEN a cancel is requested
1437 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1438 waitForIdle();
1439
1440 // It should work
1441 StatusBarNotification[] notifs =
1442 mBinderService.getActiveNotifications(PKG);
1443 assertEquals(0, notifs.length);
1444 assertEquals(0, mService.getNotificationRecordCount());
1445 }
1446
1447 @Test
1448 public void testChangeSystemTimeAfterPost_thenCancel_fgs() throws Exception {
1449 // GIVEN time X
1450 mSystemClock.setCurrentTimeMillis(10000);
1451
1452 // GIVEN a notification is posted
1453 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
1454 sbn.getNotification().flags =
1455 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1456 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
1457 sbn.getNotification(), sbn.getUserId());
1458 mSystemClock.advanceTime(1);
1459 waitForIdle();
1460
1461 // THEN the system time is changed to an earlier time
1462 mSystemClock.setCurrentTimeMillis(5000);
1463
1464 // THEN a cancel is requested
1465 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1466 waitForIdle();
1467
1468 // It should work
1469 StatusBarNotification[] notifs =
1470 mBinderService.getActiveNotifications(PKG);
1471 assertEquals(0, notifs.length);
1472 assertEquals(0, mService.getNotificationRecordCount());
1473 }
1474
1475 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001476 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001477 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1478 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001479 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001480 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001481 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1482 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001483 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001484 mBinderService.cancelNotificationWithTag(PKG, PKG,
1485 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001486 waitForIdle();
1487 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001488 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001489 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001490 assertEquals(0, mService.getNotificationRecordCount());
1491 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1492 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1493 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001494 }
1495
1496 @Test
Evan Laird3f4a62d2020-08-28 11:25:04 -04001497 public void testDelayCancelWhenEnqueuedHasNotPosted() throws Exception {
1498 // Don't allow PostNotificationRunnables to execute so we can set up problematic state
1499 mService.trapEnqueuedNotifications = true;
1500 // GIVEN an enqueued notification
1501 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1502 "testDelayCancelWhenEnqueuedHasNotPosted", 0,
1503 generateNotificationRecord(null).getNotification(), 0);
1504 mSystemClock.advanceTime(1);
1505 // WHEN a cancel is requested before it has posted
1506 mBinderService.cancelNotificationWithTag(PKG, PKG,
1507 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0);
1508
1509 waitForIdle();
1510
1511 // THEN the cancel notification runnable is captured and associated with that record
1512 ArrayMap<NotificationRecord,
1513 ArrayList<NotificationManagerService.CancelNotificationRunnable>> delayed =
1514 mService.mDelayedCancelations;
1515 Set<NotificationRecord> keySet = delayed.keySet();
1516 assertEquals(1, keySet.size());
1517 }
1518
1519 @Test
1520 public void testDelayedCancelsExecuteAfterPost() throws Exception {
1521 // Don't allow PostNotificationRunnables to execute so we can set up problematic state
1522 mService.trapEnqueuedNotifications = true;
1523 // GIVEN an enqueued notification
1524 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1525 "testDelayCancelWhenEnqueuedHasNotPosted", 0,
1526 generateNotificationRecord(null).getNotification(), 0);
1527 mSystemClock.advanceTime(1);
1528 // WHEN a cancel is requested before it has posted
1529 mBinderService.cancelNotificationWithTag(PKG, PKG,
1530 "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0);
1531
1532 waitForIdle();
1533
1534 // We're now in a state with an a notification awaiting PostNotificationRunnable to execute
1535 // WHEN the PostNotificationRunnable is allowed to execute
1536 mService.drainTrappedRunnableQueue();
1537 waitForIdle();
1538
1539 // THEN the cancel executes and the notification is removed
1540 StatusBarNotification[] notifs =
1541 mBinderService.getActiveNotifications(PKG);
1542 assertEquals(0, notifs.length);
1543 assertEquals(0, mService.getNotificationRecordCount());
1544 }
1545
1546 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001547 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001548 NotificationRecord r = generateNotificationRecord(null);
Julia Reynolds24edc002020-01-29 16:35:32 -05001549 final StatusBarNotification sbn = r.getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001550 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1551 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001552 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001553 mBinderService.cancelNotificationsFromListener(null, null);
1554 waitForIdle();
1555 StatusBarNotification[] notifs =
1556 mBinderService.getActiveNotifications(sbn.getPackageName());
1557 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001558 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001559 }
1560
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001561 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001562 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001563 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001564 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1565 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001566 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001567 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001568 waitForIdle();
1569 StatusBarNotification[] notifs =
1570 mBinderService.getActiveNotifications(sbn.getPackageName());
1571 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001572 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001573 }
1574
1575 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001576 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1577 throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001578 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001579 sbn.getNotification().flags =
1580 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1581 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1582 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1583 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1584 waitForIdle();
1585 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1586 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1587 }
1588
1589 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001590 public void testUserInitiatedClearAll_noLeak() throws Exception {
1591 final NotificationRecord n = generateNotificationRecord(
1592 mTestNotificationChannel, 1, "group", true);
1593
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001594 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1595 "testUserInitiatedClearAll_noLeak",
Julia Reynolds24edc002020-01-29 16:35:32 -05001596 n.getSbn().getId(), n.getSbn().getNotification(), n.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001597 waitForIdle();
1598
Julia Reynolds503ed942017-10-04 16:04:56 -04001599 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001600 n.getUserId());
1601 waitForIdle();
1602 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001603 mBinderService.getActiveNotifications(n.getSbn().getPackageName());
Julia Reynolds080361e2017-07-13 11:23:12 -04001604 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001605 assertEquals(0, mService.getNotificationRecordCount());
1606 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1607 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1608 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001609 }
1610
1611 @Test
1612 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1613 final NotificationRecord parent = generateNotificationRecord(
1614 mTestNotificationChannel, 1, "group1", true);
1615 final NotificationRecord child = generateNotificationRecord(
1616 mTestNotificationChannel, 2, "group1", false);
1617
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001618 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1619 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001620 parent.getSbn().getId(), parent.getSbn().getNotification(),
1621 parent.getSbn().getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001622 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1623 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds24edc002020-01-29 16:35:32 -05001624 child.getSbn().getId(), child.getSbn().getNotification(),
1625 child.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001626 waitForIdle();
1627
Julia Reynolds24edc002020-01-29 16:35:32 -05001628 mBinderService.cancelAllNotifications(PKG, parent.getSbn().getUserId());
Julia Reynolds080361e2017-07-13 11:23:12 -04001629 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001630 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001631 }
1632
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001633 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001634 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001635 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds0839c022017-06-15 15:24:01 -04001636 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001637 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1638 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001639 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1640 }
1641 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1642 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001643
Julia Reynolds503ed942017-10-04 16:04:56 -04001644 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001645 }
1646
1647 @Test
1648 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1649 final NotificationRecord parent = generateNotificationRecord(
1650 mTestNotificationChannel, 1, "group1", true);
1651 final NotificationRecord parentAsChild = generateNotificationRecord(
1652 mTestNotificationChannel, 1, "group1", false);
1653 final NotificationRecord child = generateNotificationRecord(
1654 mTestNotificationChannel, 2, "group1", false);
1655
1656 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001657 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1658 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001659 parent.getSbn().getId(), parent.getSbn().getNotification(),
1660 parent.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001661 waitForIdle();
1662
1663 // enqueue the child several times
1664 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001665 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1666 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001667 child.getSbn().getId(), child.getSbn().getNotification(),
1668 child.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001669 }
1670 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001671 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1672 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds24edc002020-01-29 16:35:32 -05001673 parentAsChild.getSbn().getId(), parentAsChild.getSbn().getNotification(),
1674 parentAsChild.getSbn().getUserId());
Julia Reynolds0839c022017-06-15 15:24:01 -04001675 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001676
Julia Reynolds503ed942017-10-04 16:04:56 -04001677 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001678 }
1679
1680 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001681 public void testAutobundledSummary_notificationAdded() {
1682 NotificationRecord summary =
1683 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1684 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1685 mService.addNotification(summary);
1686 mService.mSummaryByGroupKey.put("pkg", summary);
1687 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1688 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001689 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001690
Julia Reynolds24edc002020-01-29 16:35:32 -05001691 assertTrue(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001692 }
1693
1694 @Test
1695 public void testAutobundledSummary_notificationRemoved() {
1696 NotificationRecord summary =
1697 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1698 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1699 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1700 mService.addNotification(summary);
1701 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1702 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1703 mService.mSummaryByGroupKey.put("pkg", summary);
1704
Mady Mellor6d775f82019-11-12 16:12:19 -08001705 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001706
Julia Reynolds24edc002020-01-29 16:35:32 -05001707 assertFalse(summary.getSbn().isOngoing());
Jay Aliomerefe1c922019-09-19 16:42:16 -04001708 }
1709
1710 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001711 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001712 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001713 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001714 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1715 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001716 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001717 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001718 waitForIdle();
1719 StatusBarNotification[] notifs =
1720 mBinderService.getActiveNotifications(sbn.getPackageName());
1721 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001722 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001723 }
1724
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001725 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001726 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001727 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldse5c60452018-04-30 14:41:36 -04001728 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001729 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1730 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001731 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001732 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1733 waitForIdle();
1734 StatusBarNotification[] notifs =
1735 mBinderService.getActiveNotifications(sbn.getPackageName());
1736 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001737 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001738 }
1739
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001740 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001741 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001742 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001743 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1744 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001745 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001746 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1747 waitForIdle();
1748 StatusBarNotification[] notifs =
1749 mBinderService.getActiveNotifications(sbn.getPackageName());
1750 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001751 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001752 }
1753
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001754 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001755 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001756 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001757 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1758 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001759 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001760 // Null pkg is how we signal a user switch.
1761 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1762 waitForIdle();
1763 StatusBarNotification[] notifs =
1764 mBinderService.getActiveNotifications(sbn.getPackageName());
1765 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001766 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001767 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001768
1769 @Test
Beverly40239d92017-07-07 10:20:41 -04001770 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001771 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Beverly40239d92017-07-07 10:20:41 -04001772 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001773 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1774 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001775 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1776 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1777 waitForIdle();
1778 StatusBarNotification[] notifs =
1779 mBinderService.getActiveNotifications(sbn.getPackageName());
1780 assertEquals(0, notifs.length);
1781 }
1782
1783 @Test
1784 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1785 final NotificationRecord notif = generateNotificationRecord(
1786 mTestNotificationChannel, 1, "group", true);
1787 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001788 mService.addNotification(notif);
1789 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001790 notif.getUserId(), 0, null);
1791 waitForIdle();
1792 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001793 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001794 assertEquals(0, notifs.length);
1795 }
1796
1797 @Test
1798 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1799 final NotificationRecord notif = generateNotificationRecord(
1800 mTestNotificationChannel, 1, "group", true);
1801 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001802 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001803
Julia Reynolds503ed942017-10-04 16:04:56 -04001804 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001805 notif.getUserId());
1806 waitForIdle();
1807 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001808 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001809 assertEquals(1, notifs.length);
1810 }
1811
1812 @Test
1813 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1814 final NotificationRecord parent = generateNotificationRecord(
1815 mTestNotificationChannel, 1, "group", true);
1816 final NotificationRecord child = generateNotificationRecord(
1817 mTestNotificationChannel, 2, "group", false);
1818 final NotificationRecord child2 = generateNotificationRecord(
1819 mTestNotificationChannel, 3, "group", false);
1820 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1821 final NotificationRecord newGroup = generateNotificationRecord(
1822 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001823 mService.addNotification(parent);
1824 mService.addNotification(child);
1825 mService.addNotification(child2);
1826 mService.addNotification(newGroup);
1827 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001828 waitForIdle();
1829 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001830 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001831 assertEquals(1, notifs.length);
1832 }
1833
1834 @Test
1835 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1836 final NotificationRecord parent = generateNotificationRecord(
1837 mTestNotificationChannel, 1, "group", true);
1838 final NotificationRecord child = generateNotificationRecord(
1839 mTestNotificationChannel, 2, "group", false);
1840 final NotificationRecord child2 = generateNotificationRecord(
1841 mTestNotificationChannel, 3, "group", false);
1842 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1843 final NotificationRecord newGroup = generateNotificationRecord(
1844 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001845 mService.addNotification(parent);
1846 mService.addNotification(child);
1847 mService.addNotification(child2);
1848 mService.addNotification(newGroup);
1849 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001850 parent.getUserId());
1851 waitForIdle();
1852 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001853 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Beverly40239d92017-07-07 10:20:41 -04001854 assertEquals(1, notifs.length);
1855 }
1856
1857 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001858 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001859 Notification n =
1860 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1861 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1862 .build();
1863 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04001864 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001865 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001866 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001867 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001868 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1869 sbn.getUserId());
1870 waitForIdle();
1871 StatusBarNotification[] notifs =
1872 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001873 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001874 }
1875
1876 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001877 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05001878 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001879 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001880 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001881 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001882 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1883 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001884 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001885 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001886 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1887 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001888 waitForIdle();
1889 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001890 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001891 }
1892
1893 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001894 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1895 throws Exception {
1896 final NotificationRecord parent = generateNotificationRecord(
1897 mTestNotificationChannel, 1, "group", true);
1898 final NotificationRecord child = generateNotificationRecord(
1899 mTestNotificationChannel, 2, "group", false);
1900 final NotificationRecord child2 = generateNotificationRecord(
1901 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001902 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001903 final NotificationRecord newGroup = generateNotificationRecord(
1904 mTestNotificationChannel, 4, "group2", false);
1905 mService.addNotification(parent);
1906 mService.addNotification(child);
1907 mService.addNotification(child2);
1908 mService.addNotification(newGroup);
1909 mService.getBinderService().cancelNotificationsFromListener(null, null);
1910 waitForIdle();
1911 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001912 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001913 assertEquals(0, notifs.length);
1914 }
1915
1916 @Test
1917 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1918 throws Exception {
1919 final NotificationRecord parent = generateNotificationRecord(
1920 mTestNotificationChannel, 1, "group", true);
1921 final NotificationRecord child = generateNotificationRecord(
1922 mTestNotificationChannel, 2, "group", false);
1923 final NotificationRecord child2 = generateNotificationRecord(
1924 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001925 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001926 final NotificationRecord newGroup = generateNotificationRecord(
1927 mTestNotificationChannel, 4, "group2", false);
1928 mService.addNotification(parent);
1929 mService.addNotification(child);
1930 mService.addNotification(child2);
1931 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05001932 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
1933 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05001934 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1935 waitForIdle();
1936 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001937 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001938 assertEquals(1, notifs.length);
1939 }
1940
1941 @Test
1942 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1943 final NotificationRecord parent = generateNotificationRecord(
1944 mTestNotificationChannel, 1, "group", true);
1945 final NotificationRecord child = generateNotificationRecord(
1946 mTestNotificationChannel, 2, "group", false);
1947 final NotificationRecord child2 = generateNotificationRecord(
1948 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001949 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001950 final NotificationRecord newGroup = generateNotificationRecord(
1951 mTestNotificationChannel, 4, "group2", false);
1952 mService.addNotification(parent);
1953 mService.addNotification(child);
1954 mService.addNotification(child2);
1955 mService.addNotification(newGroup);
1956 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1957 parent.getUserId());
1958 waitForIdle();
1959 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05001960 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05001961 assertEquals(0, notifs.length);
1962 }
1963
1964 @Test
Will Brockman8da8c8e2020-04-30 12:46:15 -04001965 public void testGroupInstanceIds() throws Exception {
1966 final NotificationRecord group1 = generateNotificationRecord(
1967 mTestNotificationChannel, 1, "group1", true);
1968 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1969 group1.getSbn().getId(), group1.getSbn().getNotification(),
1970 group1.getSbn().getUserId());
1971 waitForIdle();
1972
1973 // same group, child, should be returned
1974 final NotificationRecord group1Child = generateNotificationRecord(
1975 mTestNotificationChannel, 2, "group1", false);
1976 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1977 group1Child.getSbn().getId(),
1978 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
1979 waitForIdle();
1980
1981 assertEquals(2, mNotificationRecordLogger.numCalls());
1982 assertEquals(mNotificationRecordLogger.get(0).getInstanceId(),
1983 mNotificationRecordLogger.get(1).groupInstanceId.getId());
1984 }
1985
1986 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001987 public void testFindGroupNotificationsLocked() throws Exception {
1988 // make sure the same notification can be found in both lists and returned
1989 final NotificationRecord group1 = generateNotificationRecord(
1990 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001991 mService.addEnqueuedNotification(group1);
1992 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001993
1994 // should not be returned
1995 final NotificationRecord group2 = generateNotificationRecord(
1996 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001997 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05001998 group2.getSbn().getId(), group2.getSbn().getNotification(),
1999 group2.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002000 waitForIdle();
2001
2002 // should not be returned
2003 final NotificationRecord nonGroup = generateNotificationRecord(
2004 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002005 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05002006 nonGroup.getSbn().getId(), nonGroup.getSbn().getNotification(),
2007 nonGroup.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002008 waitForIdle();
2009
2010 // same group, child, should be returned
2011 final NotificationRecord group1Child = generateNotificationRecord(
2012 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002013 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynolds24edc002020-01-29 16:35:32 -05002014 group1Child.getSbn().getId(),
2015 group1Child.getSbn().getNotification(), group1Child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002016 waitForIdle();
2017
2018 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04002019 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynolds24edc002020-01-29 16:35:32 -05002020 group1.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002021 assertEquals(3, inGroup1.size());
2022 for (NotificationRecord record : inGroup1) {
2023 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
Julia Reynolds24edc002020-01-29 16:35:32 -05002024 assertTrue(record.getSbn().getId() == 1 || record.getSbn().getId() == 4);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002025 }
2026 }
2027
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002028 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05002029 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
2030 final NotificationRecord notif = generateNotificationRecord(
2031 mTestNotificationChannel, 1, "group", true);
2032 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2033 mService.addNotification(notif);
2034 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
2035 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
2036 waitForIdle();
2037 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002038 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002039 assertEquals(0, notifs.length);
2040 }
2041
2042 @Test
2043 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
2044 throws Exception {
2045 final NotificationRecord parent = generateNotificationRecord(
2046 mTestNotificationChannel, 1, "group", true);
2047 final NotificationRecord child = generateNotificationRecord(
2048 mTestNotificationChannel, 2, "group", false);
2049 final NotificationRecord child2 = generateNotificationRecord(
2050 mTestNotificationChannel, 3, "group", false);
2051 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
2052 final NotificationRecord newGroup = generateNotificationRecord(
2053 mTestNotificationChannel, 4, "group2", false);
2054 mService.addNotification(parent);
2055 mService.addNotification(child);
2056 mService.addNotification(child2);
2057 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05002058 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2059 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05002060 mService.getBinderService().cancelNotificationsFromListener(null, keys);
2061 waitForIdle();
2062 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002063 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002064 assertEquals(0, notifs.length);
2065 }
2066
2067 @Test
2068 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
Julia Reynolds24edc002020-01-29 16:35:32 -05002069 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynolds40f00d72017-12-12 10:47:32 -05002070 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002071 mBinderService.enqueueNotificationWithTag(PKG, PKG,
2072 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05002073 sbn.getId(), sbn.getNotification(), sbn.getUserId());
2074 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
2075 waitForIdle();
2076 StatusBarNotification[] notifs =
2077 mBinderService.getActiveNotifications(sbn.getPackageName());
2078 assertEquals(0, notifs.length);
2079 }
2080
2081 @Test
2082 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
2083 final NotificationRecord notif = generateNotificationRecord(
2084 mTestNotificationChannel, 1, "group", true);
2085 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2086 mService.addNotification(notif);
2087 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
2088 notif.getUserId(), 0, null);
2089 waitForIdle();
2090 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002091 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002092 assertEquals(0, notifs.length);
2093 }
2094
2095 @Test
2096 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
2097 final NotificationRecord notif = generateNotificationRecord(
2098 mTestNotificationChannel, 1, "group", true);
2099 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2100 mService.addNotification(notif);
2101
2102 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2103 notif.getUserId());
2104 waitForIdle();
2105 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002106 mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002107 assertEquals(1, notifs.length);
2108 }
2109
2110 @Test
2111 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
2112 final NotificationRecord parent = generateNotificationRecord(
2113 mTestNotificationChannel, 1, "group", true);
2114 final NotificationRecord child = generateNotificationRecord(
2115 mTestNotificationChannel, 2, "group", false);
2116 final NotificationRecord child2 = generateNotificationRecord(
2117 mTestNotificationChannel, 3, "group", false);
2118 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2119 final NotificationRecord newGroup = generateNotificationRecord(
2120 mTestNotificationChannel, 4, "group2", false);
2121 mService.addNotification(parent);
2122 mService.addNotification(child);
2123 mService.addNotification(child2);
2124 mService.addNotification(newGroup);
2125 mService.getBinderService().cancelNotificationsFromListener(null, null);
2126 waitForIdle();
2127 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002128 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002129 assertEquals(1, notifs.length);
2130 }
2131
2132 @Test
2133 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
2134 throws Exception {
2135 final NotificationRecord parent = generateNotificationRecord(
2136 mTestNotificationChannel, 1, "group", true);
2137 final NotificationRecord child = generateNotificationRecord(
2138 mTestNotificationChannel, 2, "group", false);
2139 final NotificationRecord child2 = generateNotificationRecord(
2140 mTestNotificationChannel, 3, "group", false);
2141 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2142 final NotificationRecord newGroup = generateNotificationRecord(
2143 mTestNotificationChannel, 4, "group2", false);
2144 mService.addNotification(parent);
2145 mService.addNotification(child);
2146 mService.addNotification(child2);
2147 mService.addNotification(newGroup);
Julia Reynolds24edc002020-01-29 16:35:32 -05002148 String[] keys = {parent.getSbn().getKey(), child.getSbn().getKey(),
2149 child2.getSbn().getKey(), newGroup.getSbn().getKey()};
Julia Reynolds40f00d72017-12-12 10:47:32 -05002150 mService.getBinderService().cancelNotificationsFromListener(null, keys);
2151 waitForIdle();
2152 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002153 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002154 assertEquals(0, notifs.length);
2155 }
2156
2157 @Test
2158 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
2159 final NotificationRecord parent = generateNotificationRecord(
2160 mTestNotificationChannel, 1, "group", true);
2161 final NotificationRecord child = generateNotificationRecord(
2162 mTestNotificationChannel, 2, "group", false);
2163 final NotificationRecord child2 = generateNotificationRecord(
2164 mTestNotificationChannel, 3, "group", false);
2165 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
2166 final NotificationRecord newGroup = generateNotificationRecord(
2167 mTestNotificationChannel, 4, "group2", false);
2168 mService.addNotification(parent);
2169 mService.addNotification(child);
2170 mService.addNotification(child2);
2171 mService.addNotification(newGroup);
2172 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
2173 parent.getUserId());
2174 waitForIdle();
2175 StatusBarNotification[] notifs =
Julia Reynolds24edc002020-01-29 16:35:32 -05002176 mBinderService.getActiveNotifications(parent.getSbn().getPackageName());
Julia Reynolds40f00d72017-12-12 10:47:32 -05002177 assertEquals(1, notifs.length);
2178 }
2179
2180 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002181 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002182 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002183 mService.setPreferencesHelper(mPreferencesHelper);
2184 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002185 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002186 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002187
Julia Reynoldsbad42972017-04-25 13:52:49 -04002188 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002189 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04002190 generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002191 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
2192 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002193 }
2194
2195 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002196 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002197 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002198 mService.setPreferencesHelper(mPreferencesHelper);
2199 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002200 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05002201 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002202
Julia Reynoldsbad42972017-04-25 13:52:49 -04002203 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002204 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
2205 0, generateNotificationRecord(null, tv).getNotification(), 0);
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002206 verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
Julia Reynolds0f767342019-12-18 09:11:55 -05002207 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05002208 anyBoolean(), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05002209 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002210
2211 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002212 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002213 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002214
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002215 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002216 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2217 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2218
2219 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2220 captor.getValue().getAction());
2221 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04002222 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2223 }
2224
2225 @Test
2226 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
2227 mService.setPreferencesHelper(mPreferencesHelper);
2228
2229 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
2230 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002231 }
2232
2233 @Test
2234 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002235 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05002236
2237 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
2238 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2239 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2240
2241 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
2242 captor.getValue().getAction());
2243 assertEquals(PKG, captor.getValue().getPackage());
2244 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
2245 }
2246
2247 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002248 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002249 mService.setPreferencesHelper(mPreferencesHelper);
2250 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002251 eq(mTestNotificationChannel.getId()), anyBoolean()))
2252 .thenReturn(mTestNotificationChannel);
2253
2254 NotificationChannel updatedChannel =
2255 new NotificationChannel(mTestNotificationChannel.getId(),
2256 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
2257
2258 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
2259 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2260 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2261
2262 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2263 captor.getValue().getAction());
2264 assertEquals(PKG, captor.getValue().getPackage());
2265 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002266 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002267 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2268 }
2269
2270 @Test
2271 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
2272 NotificationChannel existingChannel =
2273 new NotificationChannel(mTestNotificationChannel.getId(),
2274 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002275 mService.setPreferencesHelper(mPreferencesHelper);
2276 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002277 eq(mTestNotificationChannel.getId()), anyBoolean()))
2278 .thenReturn(existingChannel);
2279
2280 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2281 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2282 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2283
2284 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
2285 captor.getValue().getAction());
2286 assertEquals(PKG, captor.getValue().getPackage());
2287 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002288 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002289 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2290 }
2291
2292 @Test
2293 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
2294 NotificationChannel existingChannel =
2295 new NotificationChannel(mTestNotificationChannel.getId(),
2296 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002297 mService.setPreferencesHelper(mPreferencesHelper);
2298 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002299 eq(mTestNotificationChannel.getId()), anyBoolean()))
2300 .thenReturn(existingChannel);
2301
2302 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
2303 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2304 }
2305
2306 @Test
2307 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
2308 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002309 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002310 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2311 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002312 .thenReturn(existing);
2313
2314 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
2315 updated.setBlocked(true);
2316
2317 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
2318 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2319 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2320
2321 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2322 captor.getValue().getAction());
2323 assertEquals(PKG, captor.getValue().getPackage());
2324 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002325 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002326 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2327 }
2328
2329 @Test
2330 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
2331 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
2332 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002333 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002334 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()),
2335 eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002336 .thenReturn(existing);
2337
2338 mBinderService.updateNotificationChannelGroupForPackage(
2339 PKG, 0, new NotificationChannelGroup("id", "name"));
2340 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
2341 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
2342
2343 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
2344 captor.getValue().getAction());
2345 assertEquals(PKG, captor.getValue().getPackage());
2346 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05002347 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002348 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
2349 }
2350
2351 @Test
2352 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
2353 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002354 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds24edc002020-01-29 16:35:32 -05002355 when(mPreferencesHelper.getNotificationChannelGroup(
2356 eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002357 .thenReturn(existing);
2358
2359 mBinderService.updateNotificationChannelGroupForPackage(
2360 PKG, 0, new NotificationChannelGroup("id", "new name"));
2361 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
2362 }
2363
2364 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002365 public void testCreateChannelNotifyListener() throws Exception {
2366 List<String> associations = new ArrayList<>();
2367 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002368 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2369 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002370 mService.setPreferencesHelper(mPreferencesHelper);
2371 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002372 eq(mTestNotificationChannel.getId()), anyBoolean()))
2373 .thenReturn(mTestNotificationChannel);
2374 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002375 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002376 eq(channel2.getId()), anyBoolean()))
2377 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002378 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
2379 eq(channel2), anyBoolean(), anyBoolean()))
2380 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002381
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002382 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002383 mBinderService.createNotificationChannels(PKG,
2384 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04002385 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002386 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002387 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002388 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002389 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002390 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2391 }
2392
2393 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002394 public void testCreateChannelGroupNotifyListener() throws Exception {
2395 List<String> associations = new ArrayList<>();
2396 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002397 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2398 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002399 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002400 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
2401 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
2402
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002403 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002404 mBinderService.createNotificationChannelGroups(PKG,
2405 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002406 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002407 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002408 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002409 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002410 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002411 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
2412 }
2413
2414 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002415 public void testUpdateChannelNotifyListener() throws Exception {
2416 List<String> associations = new ArrayList<>();
2417 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002418 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2419 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002420 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002421 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002422 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002423 eq(mTestNotificationChannel.getId()), anyBoolean()))
2424 .thenReturn(mTestNotificationChannel);
2425
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002426 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002427 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002428 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002429 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002430 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2431 }
2432
2433 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002434 public void testDeleteChannelNotifyListener() throws Exception {
2435 List<String> associations = new ArrayList<>();
2436 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002437 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2438 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002439 mService.setPreferencesHelper(mPreferencesHelper);
2440 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002441 eq(mTestNotificationChannel.getId()), anyBoolean()))
2442 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002443 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002444 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002445 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002446 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002447 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2448 }
2449
2450 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002451 public void testDeleteChannelGroupNotifyListener() throws Exception {
2452 List<String> associations = new ArrayList<>();
2453 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002454 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2455 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002456 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002457 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds59376062022-01-07 16:28:52 -05002458 when(mPreferencesHelper.getNotificationChannelGroupWithChannels(
2459 eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002460 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002461 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002462 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002463 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002464 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002465 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
2466 }
2467
2468 @Test
Julia Reynolds59376062022-01-07 16:28:52 -05002469 public void testDeleteChannelGroupChecksForFgses() throws Exception {
2470 List<String> associations = new ArrayList<>();
2471 associations.add("a");
2472 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2473 .thenReturn(associations);
2474 CountDownLatch latch = new CountDownLatch(2);
2475 mService.createNotificationChannelGroup(
2476 PKG, mUid, new NotificationChannelGroup("group", "group"), true, false);
2477 new Thread(() -> {
2478 NotificationChannel notificationChannel = new NotificationChannel("id", "id",
2479 NotificationManager.IMPORTANCE_HIGH);
2480 notificationChannel.setGroup("group");
2481 ParceledListSlice<NotificationChannel> pls =
2482 new ParceledListSlice(ImmutableList.of(notificationChannel));
2483 try {
2484 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
2485 } catch (RemoteException e) {
2486 throw new RuntimeException(e);
2487 }
2488 latch.countDown();
2489 }).start();
2490 new Thread(() -> {
2491 try {
2492 synchronized (this) {
2493 wait(5000);
2494 }
2495 mService.createNotificationChannelGroup(PKG, mUid,
2496 new NotificationChannelGroup("new", "new group"), true, false);
2497 NotificationChannel notificationChannel =
2498 new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
2499 notificationChannel.setGroup("new");
2500 ParceledListSlice<NotificationChannel> pls =
2501 new ParceledListSlice(ImmutableList.of(notificationChannel));
2502 try {
2503 mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
2504 mBinderService.deleteNotificationChannelGroup(PKG, "group");
2505 } catch (RemoteException e) {
2506 throw new RuntimeException(e);
2507 }
2508 } catch (Exception e) {
2509 e.printStackTrace();
2510 }
2511 latch.countDown();
2512 }).start();
2513
2514 latch.await();
2515 verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString());
2516 }
2517
2518 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002519 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002520 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002521 List<String> associations = new ArrayList<>();
2522 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002523 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2524 .thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002525 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05002526 eq(mTestNotificationChannel.getId()), anyBoolean()))
2527 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002528
2529 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002530 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002531
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002532 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002533 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002534
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002535 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002536 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002537 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2538 }
2539
2540 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002541 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002542 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002543 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002544 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2545 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002546
2547 try {
2548 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002549 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002550 fail("listeners that don't have a companion device shouldn't be able to call this");
2551 } catch (SecurityException e) {
2552 // pass
2553 }
2554
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002555 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002556 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002557
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002558 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002559 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
2560 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2561 }
2562
2563 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002564 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002565 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002566 List<String> associations = new ArrayList<>();
2567 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002568 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2569 .thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002570 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002571 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002572 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002573 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002574
2575 try {
2576 mBinderService.updateNotificationChannelFromPrivilegedListener(
2577 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2578 fail("incorrectly allowed a change to a user listener cannot see");
2579 } catch (SecurityException e) {
2580 // pass
2581 }
2582
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002583 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002584 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002585
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002586 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002587 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002588 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2589 }
2590
2591 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002592 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002593 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002594 List<String> associations = new ArrayList<>();
2595 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002596 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2597 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002598
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002599 mBinderService.getNotificationChannelsFromPrivilegedListener(
2600 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002601
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002602 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002603 anyString(), anyInt(), anyBoolean());
2604 }
2605
2606 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002607 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002608 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002609 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002610 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2611 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002612
2613 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002614 mBinderService.getNotificationChannelsFromPrivilegedListener(
2615 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002616 fail("listeners that don't have a companion device shouldn't be able to call this");
2617 } catch (SecurityException e) {
2618 // pass
2619 }
2620
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002621 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002622 anyString(), anyInt(), anyBoolean());
2623 }
2624
2625 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002626 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2627 throws Exception {
2628 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldse61758a2020-06-10 10:26:44 -04002629 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2630 .thenReturn(new ArrayList<>());
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002631 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2632
2633 mBinderService.getNotificationChannelsFromPrivilegedListener(
2634 null, PKG, Process.myUserHandle());
2635
2636 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2637 anyString(), anyInt(), anyBoolean());
2638 }
2639
2640 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002641 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2642 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002643 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldse61758a2020-06-10 10:26:44 -04002644 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2645 .thenReturn(new ArrayList<>());
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002646 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2647
2648 try {
2649 mBinderService.getNotificationChannelsFromPrivilegedListener(
2650 null, PKG, Process.myUserHandle());
2651 fail("listeners that don't have a companion device shouldn't be able to call this");
2652 } catch (SecurityException e) {
2653 // pass
2654 }
2655
2656 verify(mPreferencesHelper, never()).getNotificationChannels(
2657 anyString(), anyInt(), anyBoolean());
2658 }
2659
2660 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002661 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002662 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002663 List<String> associations = new ArrayList<>();
2664 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002665 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2666 .thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002667 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2668 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002669 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002670
2671 try {
2672 mBinderService.getNotificationChannelsFromPrivilegedListener(
2673 null, PKG, Process.myUserHandle());
2674 fail("listener getting channels from a user they cannot see");
2675 } catch (SecurityException e) {
2676 // pass
2677 }
2678
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002679 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002680 anyString(), anyInt(), anyBoolean());
2681 }
2682
2683 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002684 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002685 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002686 List<String> associations = new ArrayList<>();
2687 associations.add("a");
Julia Reynoldse61758a2020-06-10 10:26:44 -04002688 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2689 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002690
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002691 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2692 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002693
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002694 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002695 }
2696
2697 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002698 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002699 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002700 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002701 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2702 .thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002703
2704 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002705 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2706 null, PKG, Process.myUserHandle());
2707 fail("listeners that don't have a companion device shouldn't be able to call this");
2708 } catch (SecurityException e) {
2709 // pass
2710 }
2711
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002712 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002713 }
2714
2715 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002716 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002717 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002718 List<String> associations = new ArrayList<>();
Julia Reynoldse61758a2020-06-10 10:26:44 -04002719 when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
2720 .thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002721 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2722 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002723 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002724 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002725 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2726 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002727 fail("listeners that don't have a companion device shouldn't be able to call this");
2728 } catch (SecurityException e) {
2729 // pass
2730 }
2731
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002732 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002733 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002734
2735 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002736 public void testHasCompanionDevice_failure() throws Exception {
2737 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2738 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002739 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002740 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002741
2742 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002743 public void testHasCompanionDevice_noService() {
Evan Laird3f4a62d2020-08-28 11:25:04 -04002744 mService =
2745 new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
2746 mSystemClock, mNotificationInstanceIdSequence);
Julia Reynolds727a7282017-04-13 10:54:01 -04002747
Julia Reynolds503ed942017-10-04 16:04:56 -04002748 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002749 }
2750
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002751 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002752 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2753 final NotificationRecord notification = generateNotificationRecord(
2754 mTestNotificationChannel, 1, null, true);
2755 mService.addNotification(notification);
2756 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2757
2758 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2759 mService.new SnoozeNotificationRunnable(
2760 notification.getKey(), 100, null);
2761 snoozeNotificationRunnable.run();
2762 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2763 mService.new SnoozeNotificationRunnable(
2764 notification.getKey(), 100, null);
2765 snoozeNotificationRunnable.run();
2766
2767 // snooze twice
2768 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2769 }
2770
2771 @Test
2772 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2773 final NotificationRecord notification = generateNotificationRecord(
2774 mTestNotificationChannel, 1, "group", true);
2775 mService.addNotification(notification);
2776 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2777
2778 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2779 mService.new SnoozeNotificationRunnable(
2780 notification.getKey(), 100, null);
2781 snoozeNotificationRunnable.run();
2782 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2783 mService.new SnoozeNotificationRunnable(
2784 notification.getKey(), 100, null);
2785 snoozeNotificationRunnable.run();
2786
2787 // snooze twice
2788 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2789 }
2790
2791 @Test
2792 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2793 final NotificationRecord notification = generateNotificationRecord(
2794 mTestNotificationChannel, 1, "group", true);
2795 final NotificationRecord notification2 = generateNotificationRecord(
2796 mTestNotificationChannel, 2, "group", true);
2797 mService.addNotification(notification);
2798 mService.addNotification(notification2);
2799 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2800 when(mSnoozeHelper.getNotifications(
2801 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2802
2803 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2804 mService.new SnoozeNotificationRunnable(
2805 notification.getKey(), 100, null);
2806 snoozeNotificationRunnable.run();
2807 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2808 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2809 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2810 mService.new SnoozeNotificationRunnable(
2811 notification.getKey(), 100, null);
2812 snoozeNotificationRunnable.run();
2813
2814 // snooze twice
2815 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2816 }
2817
2818 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002819 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2820 final NotificationRecord nonGrouped = generateNotificationRecord(
2821 mTestNotificationChannel, 1, null, false);
2822 final NotificationRecord grouped = generateNotificationRecord(
2823 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002824 mService.addNotification(grouped);
2825 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002826
2827 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002828 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002829 nonGrouped.getKey(), 100, null);
2830 snoozeNotificationRunnable.run();
2831
2832 // only snooze the one notification
2833 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002834 assertTrue(nonGrouped.getStats().hasSnoozed());
Will Brockman9918db92020-03-06 16:48:39 -05002835
2836 assertEquals(2, mNotificationRecordLogger.numCalls());
2837 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2838 mNotificationRecordLogger.event(0));
2839 assertEquals(
2840 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2841 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002842 }
2843
2844 @Test
2845 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2846 final NotificationRecord parent = generateNotificationRecord(
2847 mTestNotificationChannel, 1, "group", true);
2848 final NotificationRecord child = generateNotificationRecord(
2849 mTestNotificationChannel, 2, "group", false);
2850 final NotificationRecord child2 = generateNotificationRecord(
2851 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002852 mService.addNotification(parent);
2853 mService.addNotification(child);
2854 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002855
2856 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002857 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002858 parent.getKey(), 100, null);
2859 snoozeNotificationRunnable.run();
2860
2861 // snooze parent and children
2862 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2863 }
2864
2865 @Test
2866 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2867 final NotificationRecord parent = generateNotificationRecord(
2868 mTestNotificationChannel, 1, "group", true);
2869 final NotificationRecord child = generateNotificationRecord(
2870 mTestNotificationChannel, 2, "group", false);
2871 final NotificationRecord child2 = generateNotificationRecord(
2872 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002873 mService.addNotification(parent);
2874 mService.addNotification(child);
2875 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002876
2877 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002878 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002879 child2.getKey(), 100, null);
2880 snoozeNotificationRunnable.run();
2881
2882 // only snooze the one child
2883 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002884
2885 assertEquals(2, mNotificationRecordLogger.numCalls());
2886 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2887 mNotificationRecordLogger.event(0));
2888 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
2889 .NOTIFICATION_CANCEL_SNOOZED, mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002890 }
2891
2892 @Test
2893 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2894 final NotificationRecord parent = generateNotificationRecord(
2895 mTestNotificationChannel, 1, "group", true);
Julia Reynolds24edc002020-01-29 16:35:32 -05002896 assertTrue(parent.getSbn().getNotification().isGroupSummary());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002897 final NotificationRecord child = generateNotificationRecord(
2898 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002899 mService.addNotification(parent);
2900 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002901
2902 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002903 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002904 child.getKey(), 100, null);
2905 snoozeNotificationRunnable.run();
2906
2907 // snooze child and summary
2908 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002909
2910 assertEquals(4, mNotificationRecordLogger.numCalls());
2911 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2912 mNotificationRecordLogger.event(0));
2913 assertEquals(
2914 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2915 mNotificationRecordLogger.event(1));
2916 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2917 mNotificationRecordLogger.event(2));
2918 assertEquals(
2919 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2920 mNotificationRecordLogger.event(3));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002921 }
2922
2923 @Test
2924 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2925 final NotificationRecord child = generateNotificationRecord(
2926 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002927 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002928
2929 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002930 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002931 child.getKey(), 100, null);
2932 snoozeNotificationRunnable.run();
2933
2934 // snooze child only
2935 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Will Brockman9918db92020-03-06 16:48:39 -05002936
2937 assertEquals(2, mNotificationRecordLogger.numCalls());
2938 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SNOOZED,
2939 mNotificationRecordLogger.event(0));
2940 assertEquals(
2941 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_SNOOZED,
2942 mNotificationRecordLogger.event(1));
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002943 }
2944
2945 @Test
2946 public void testPostGroupChild_unsnoozeParent() throws Exception {
2947 final NotificationRecord child = generateNotificationRecord(
2948 mTestNotificationChannel, 2, "group", false);
2949
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002950 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002951 child.getSbn().getId(), child.getSbn().getNotification(),
2952 child.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002953 waitForIdle();
2954
2955 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2956 anyString(), anyInt(), eq(child.getGroupKey()));
2957 }
2958
2959 @Test
2960 public void testPostNonGroup_noUnsnoozing() throws Exception {
2961 final NotificationRecord record = generateNotificationRecord(
2962 mTestNotificationChannel, 2, null, false);
2963
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002964 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002965 record.getSbn().getId(), record.getSbn().getNotification(),
2966 record.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002967 waitForIdle();
2968
2969 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2970 }
2971
2972 @Test
2973 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2974 final NotificationRecord parent = generateNotificationRecord(
2975 mTestNotificationChannel, 2, "group", true);
2976
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002977 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynolds24edc002020-01-29 16:35:32 -05002978 parent.getSbn().getId(), parent.getSbn().getNotification(),
2979 parent.getSbn().getUserId());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002980 waitForIdle();
2981
2982 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2983 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002984
2985 @Test
Julia Reynolds0d073782020-02-13 16:07:52 -05002986 public void testSystemNotificationListenerCanUnsnooze() throws Exception {
2987 final NotificationRecord nr = generateNotificationRecord(
2988 mTestNotificationChannel, 2, "group", false);
2989
2990 mBinderService.enqueueNotificationWithTag(PKG, PKG,
2991 "testSystemNotificationListenerCanUnsnooze",
2992 nr.getSbn().getId(), nr.getSbn().getNotification(),
2993 nr.getSbn().getUserId());
2994 waitForIdle();
2995 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2996 mService.new SnoozeNotificationRunnable(
2997 nr.getKey(), 100, null);
2998 snoozeNotificationRunnable.run();
2999
3000 ManagedServices.ManagedServiceInfo listener = mListeners.new ManagedServiceInfo(
3001 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
3002 listener.isSystem = true;
3003 when(mListeners.checkServiceTokenLocked(any())).thenReturn(listener);
3004
3005 mBinderService.unsnoozeNotificationFromSystemListener(null, nr.getKey());
3006 waitForIdle();
3007 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
3008 assertEquals(1, notifs.length);
3009 assertNotNull(notifs[0].getKey());//mService.getNotificationRecord(nr.getSbn().getKey()));
3010 }
3011
3012 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04003013 public void testSetListenerAccessForUser() throws Exception {
3014 UserHandle user = UserHandle.of(10);
3015 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003016 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
3017
Julia Reynolds92febc32017-10-26 11:30:31 -04003018
3019 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
3020 verify(mListeners, times(1)).setPackageOrComponentEnabled(
3021 c.flattenToString(), user.getIdentifier(), true, true);
3022 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3023 c.flattenToString(), user.getIdentifier(), false, true);
3024 verify(mAssistants, never()).setPackageOrComponentEnabled(
3025 any(), anyInt(), anyBoolean(), anyBoolean());
3026 }
3027
3028 @Test
3029 public void testSetAssistantAccessForUser() throws Exception {
3030 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04003031 List<UserInfo> uis = new ArrayList<>();
3032 UserInfo ui = new UserInfo();
3033 ui.id = 10;
3034 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04003035 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003036 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
3037
3038 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04003039
3040 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
3041 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3042 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00003043 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04003044 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3045 c.flattenToString(), user.getIdentifier(), false, true);
3046 verify(mListeners, never()).setPackageOrComponentEnabled(
3047 any(), anyInt(), anyBoolean(), anyBoolean());
3048 }
3049
3050 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05003051 public void testGetAssistantAllowedForUser() throws Exception {
3052 UserHandle user = UserHandle.of(10);
3053 try {
3054 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
3055 } catch (IllegalStateException e) {
3056 if (!e.getMessage().contains("At most one NotificationAssistant")) {
3057 throw e;
3058 }
3059 }
3060 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
3061 }
3062
3063 @Test
3064 public void testGetAssistantAllowed() throws Exception {
3065 try {
3066 mBinderService.getAllowedNotificationAssistant();
3067 } catch (IllegalStateException e) {
3068 if (!e.getMessage().contains("At most one NotificationAssistant")) {
3069 throw e;
3070 }
3071 }
3072 verify(mAssistants, times(1)).getAllowedComponents(0);
3073 }
3074
3075 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04003076 public void testSetDndAccessForUser() throws Exception {
3077 UserHandle user = UserHandle.of(10);
3078 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003079 mBinderService.setNotificationPolicyAccessGrantedForUser(
3080 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04003081
3082 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
3083 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3084 c.getPackageName(), user.getIdentifier(), true, true);
3085 verify(mAssistants, never()).setPackageOrComponentEnabled(
3086 any(), anyInt(), anyBoolean(), anyBoolean());
3087 verify(mListeners, never()).setPackageOrComponentEnabled(
3088 any(), anyInt(), anyBoolean(), anyBoolean());
3089 }
3090
3091 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04003092 public void testSetListenerAccess() throws Exception {
3093 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003094 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04003095
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003096 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003097 c.flattenToString(), 0, true, true);
3098 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3099 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003100 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003101 any(), anyInt(), anyBoolean(), anyBoolean());
3102 }
3103
3104 @Test
3105 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04003106 List<UserInfo> uis = new ArrayList<>();
3107 UserInfo ui = new UserInfo();
3108 ui.id = 0;
3109 uis.add(ui);
3110 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04003111 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003112
3113 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04003114
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003115 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003116 c.flattenToString(), 0, true, true);
3117 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3118 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003119 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003120 any(), anyInt(), anyBoolean(), anyBoolean());
3121 }
3122
3123 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04003124 public void testSetAssistantAccess_multiProfile() throws Exception {
3125 List<UserInfo> uis = new ArrayList<>();
3126 UserInfo ui = new UserInfo();
3127 ui.id = 0;
3128 uis.add(ui);
3129 UserInfo ui10 = new UserInfo();
3130 ui10.id = 10;
3131 uis.add(ui10);
3132 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3133 ComponentName c = ComponentName.unflattenFromString("package/Component");
3134
3135 mBinderService.setNotificationAssistantAccessGranted(c, true);
3136
3137 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3138 c.flattenToString(), 0, true, true);
3139 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3140 c.flattenToString(), 10, true, true);
3141 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3142 c.flattenToString(), 0, false, true);
3143 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3144 c.flattenToString(), 10, false, true);
3145 verify(mListeners, never()).setPackageOrComponentEnabled(
3146 any(), anyInt(), anyBoolean(), anyBoolean());
3147 }
3148
3149 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05003150 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
3151 ArrayList<ComponentName> componentList = new ArrayList<>();
3152 ComponentName c = ComponentName.unflattenFromString("package/Component");
3153 componentList.add(c);
3154 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04003155 List<UserInfo> uis = new ArrayList<>();
3156 UserInfo ui = new UserInfo();
3157 ui.id = 0;
3158 uis.add(ui);
3159 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05003160
Julia Reynolds4afe2642019-05-01 08:42:24 -04003161 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05003162
3163 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3164 c.flattenToString(), 0, true, false);
3165 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3166 c.flattenToString(), 0, false, false);
3167 verify(mListeners, never()).setPackageOrComponentEnabled(
3168 any(), anyInt(), anyBoolean(), anyBoolean());
3169 }
3170
3171 @Test
3172 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04003173 List<UserInfo> uis = new ArrayList<>();
3174 UserInfo ui = new UserInfo();
3175 ui.id = 10;
3176 uis.add(ui);
3177 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05003178 ArrayList<ComponentName> componentList = new ArrayList<>();
3179 ComponentName c = ComponentName.unflattenFromString("package/Component");
3180 componentList.add(c);
3181 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04003182 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05003183
Julia Reynolds4afe2642019-05-01 08:42:24 -04003184 mBinderService.setNotificationAssistantAccessGrantedForUser(
3185 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05003186
3187 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3188 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04003189 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05003190 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3191 c.flattenToString(), user.getIdentifier(), false, false);
3192 verify(mListeners, never()).setPackageOrComponentEnabled(
3193 any(), anyInt(), anyBoolean(), anyBoolean());
3194 }
3195
3196 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04003197 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
3198 throws Exception {
3199 List<UserInfo> uis = new ArrayList<>();
3200 UserInfo ui = new UserInfo();
3201 ui.id = 0;
3202 uis.add(ui);
3203 UserInfo ui10 = new UserInfo();
3204 ui10.id = 10;
3205 uis.add(ui10);
3206 UserHandle user = ui.getUserHandle();
3207 ArrayList<ComponentName> componentList = new ArrayList<>();
3208 ComponentName c = ComponentName.unflattenFromString("package/Component");
3209 componentList.add(c);
3210 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
3211 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3212
3213 mBinderService.setNotificationAssistantAccessGrantedForUser(
3214 null, user.getIdentifier(), true);
3215
3216 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3217 c.flattenToString(), user.getIdentifier(), true, false);
3218 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3219 c.flattenToString(), ui10.id, true, false);
3220 verify(mAssistants).setUserSet(0, true);
3221 verify(mAssistants).setUserSet(10, true);
3222 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3223 c.flattenToString(), user.getIdentifier(), false, false);
3224 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3225 c.flattenToString(), ui10.id, false, false);
3226 verify(mListeners, never()).setPackageOrComponentEnabled(
3227 any(), anyInt(), anyBoolean(), anyBoolean());
3228 }
3229
3230 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04003231 public void testSetDndAccess() throws Exception {
3232 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003233
3234 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04003235
3236 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3237 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003238 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003239 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003240 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04003241 any(), anyInt(), anyBoolean(), anyBoolean());
3242 }
Julia Reynolds68263d12017-06-21 14:21:19 -04003243
3244 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003245 public void testSetListenerAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003246 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3247 ComponentName c = ComponentName.unflattenFromString("package/Component");
3248 mBinderService.setNotificationListenerAccessGranted(c, true);
3249
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003250 verify(mListeners).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003251 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003252 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003253 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003254 verify(mAssistants).migrateToXml();
3255 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04003256 }
3257
3258 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003259 public void testSetAssistantAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003260 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3261 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003262 List<UserInfo> uis = new ArrayList<>();
3263 UserInfo ui = new UserInfo();
3264 ui.id = 0;
3265 uis.add(ui);
3266 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3267
Julia Reynolds68263d12017-06-21 14:21:19 -04003268 mBinderService.setNotificationAssistantAccessGranted(c, true);
3269
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003270 verify(mListeners).migrateToXml();
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003271 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003272 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003273 verify(mAssistants).migrateToXml();
3274 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynolds68263d12017-06-21 14:21:19 -04003275 }
3276
3277 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003278 public void testSetDndAccess_onLowRam() throws Exception {
Julia Reynolds68263d12017-06-21 14:21:19 -04003279 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3280 ComponentName c = ComponentName.unflattenFromString("package/Component");
3281 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
3282
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003283 verify(mListeners).migrateToXml();
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003284 verify(mConditionProviders).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04003285 anyString(), anyInt(), anyBoolean(), anyBoolean());
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08003286 verify(mAssistants).migrateToXml();
3287 verify(mAssistants).resetDefaultAssistantsIfNecessary();
Julia Reynoldse1816412017-10-24 10:39:11 -04003288 }
3289
3290 @Test
3291 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3292 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3293 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3294 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003295
3296 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003297
3298 verify(mListeners, times(1)).setPackageOrComponentEnabled(
3299 c.flattenToString(), 0, true, true);
3300 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003301 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003302 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04003303 any(), anyInt(), anyBoolean(), anyBoolean());
3304 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04003305
3306 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04003307 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3308 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3309 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3310 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003311 List<UserInfo> uis = new ArrayList<>();
3312 UserInfo ui = new UserInfo();
3313 ui.id = 0;
3314 uis.add(ui);
3315 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
3316
3317 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003318
3319 verify(mListeners, never()).setPackageOrComponentEnabled(
3320 anyString(), anyInt(), anyBoolean(), anyBoolean());
3321 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3322 c.flattenToString(), 0, false, true);
3323 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
3324 c.flattenToString(), 0, true, true);
3325 }
3326
3327 @Test
3328 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
3329 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3330 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3331 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04003332
3333 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04003334
3335 verify(mListeners, never()).setPackageOrComponentEnabled(
3336 anyString(), anyInt(), anyBoolean(), anyBoolean());
3337 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
3338 c.getPackageName(), 0, true, true);
3339 verify(mAssistants, never()).setPackageOrComponentEnabled(
3340 any(), anyInt(), anyBoolean(), anyBoolean());
3341 }
3342
3343 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04003344 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
3345 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003346 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003347 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003348 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003349 runnable.run();
3350 waitForIdle();
3351
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003352 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003353 }
3354
3355 @Test
3356 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
3357 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003358 NotificationRecord r =
3359 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003360 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003361
3362 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003363 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003364 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003365 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003366 runnable.run();
3367 waitForIdle();
3368
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003369 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003370 }
3371
3372 @Test
3373 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
3374 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04003375 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
3376 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003377 mService.addNotification(r);
3378 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04003379
3380 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04003381 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003382 runnable.run();
3383 waitForIdle();
3384
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04003385 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04003386 }
Beverly40239d92017-07-07 10:20:41 -04003387
Julia Reynolds4db59552017-06-30 13:34:01 -04003388 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07003389 public void testDontAutogroupIfCritical() throws Exception {
3390 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
3391 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
3392 mService.addEnqueuedNotification(r);
3393 NotificationManagerService.PostNotificationRunnable runnable =
3394 mService.new PostNotificationRunnable(r.getKey());
3395 runnable.run();
3396
3397 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
3398 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
3399 runnable = mService.new PostNotificationRunnable(r.getKey());
3400 mService.addEnqueuedNotification(r);
3401
3402 runnable.run();
3403 waitForIdle();
3404
3405 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
3406 }
3407
3408 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04003409 public void testNoFakeColorizedPermission() throws Exception {
3410 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
3411 Notification.Builder nb = new Notification.Builder(mContext,
3412 mTestNotificationChannel.getId())
3413 .setContentTitle("foo")
3414 .setColorized(true)
3415 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
3416 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003417 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
3418 "testNoFakeColorizedPermission", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04003419 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04003420 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
3421
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003422 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds24edc002020-01-29 16:35:32 -05003423 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003424 waitForIdle();
3425
Julia Reynolds503ed942017-10-04 16:04:56 -04003426 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003427 PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04003428
3429 assertFalse(posted.getNotification().isColorized());
3430 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003431
3432 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003433 public void testGetNotificationCountLocked() {
3434 String sampleTagToExclude = null;
3435 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003436 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003437 NotificationRecord r =
3438 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003439 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003440
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003441 }
3442 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003443 NotificationRecord r =
3444 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04003445 mService.addNotification(r);
Julia Reynolds24edc002020-01-29 16:35:32 -05003446 sampleTagToExclude = r.getSbn().getTag();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003447 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003448 }
3449
3450 // another package
3451 Notification n =
3452 new Notification.Builder(mContext, mTestNotificationChannel.getId())
3453 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3454 .build();
3455
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04003456 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04003457 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003458 NotificationRecord otherPackage =
3459 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003460 mService.addEnqueuedNotification(otherPackage);
3461 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003462
3463 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003464 // anything that's currently enqueued or posted
Julia Reynoldse61758a2020-06-10 10:26:44 -04003465 int userId = UserHandle.getUserId(mUid);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003466 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003467 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003468 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04003469 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003470
3471 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003472 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04003473 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003474
3475 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003476 assertEquals(39, mService.getNotificationCountLocked(
3477 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003478 }
3479
3480 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04003481 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003482 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003483 mService.addNotification(r);
3484 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003485
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003486 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003487 }
3488
3489 @Test
3490 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003491 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3492 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003493 mService.addNotification(r);
3494 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003495
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003496 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04003497 }
3498
3499 @Test
3500 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04003501 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3502 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04003503 mService.addNotification(r);
3504 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04003505
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003506 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003507 }
3508
3509 @Test
3510 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04003511 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003512 NotificationManagerService.WorkerHandler handler = mock(
3513 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003514 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003515
3516 Map<String, Answer> answers = getSignalExtractorSideEffects();
3517 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04003518 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003519 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003520 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003521
3522 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
3523
Julia Reynolds503ed942017-10-04 16:04:56 -04003524 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003525 }
3526 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
3527 }
3528
3529 @Test
3530 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003531 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003532 NotificationManagerService.WorkerHandler handler = mock(
3533 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003534 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003535
3536 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003537 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003538
Julia Reynolds503ed942017-10-04 16:04:56 -04003539 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04003540 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04003541 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003542
3543 @Test
3544 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04003545 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003546 + "<ranking></ranking>"
3547 + "<enabled_listeners>"
3548 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3549 + "</enabled_listeners>"
3550 + "<enabled_assistants>"
3551 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3552 + "</enabled_assistants>"
3553 + "<dnd_apps>"
3554 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
3555 + "</dnd_apps>"
3556 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003557 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003558 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3559 false,
3560 UserHandle.USER_ALL);
3561 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3562 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
3563 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003564
3565 // numbers are inflated for setup
3566 verify(mListeners, times(1)).migrateToXml();
3567 verify(mConditionProviders, times(1)).migrateToXml();
3568 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003569 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003570 }
3571
3572 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003573 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
3574 final String upgradeXml = "<notification-policy version=\"1\">"
3575 + "<snoozed-notifications>></snoozed-notifications>"
3576 + "</notification-policy>";
3577 mService.readPolicyXml(
3578 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
3579 false,
3580 UserHandle.USER_ALL);
Julia Reynolds9050d9a2020-02-20 09:38:05 -05003581 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong());
Jay Aliomer4dc508d2019-08-06 17:36:31 -04003582 }
3583
3584 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003585 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
3586 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003587 + "<ranking></ranking>"
3588 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04003589 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00003590 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
3591 false,
3592 UserHandle.USER_ALL);
3593 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
3594 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
3595 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003596
3597 // numbers are inflated for setup
3598 verify(mListeners, times(2)).migrateToXml();
3599 verify(mConditionProviders, times(2)).migrateToXml();
3600 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00003601 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04003602 }
3603
Annie Meng8b646fd2019-02-01 18:46:42 +00003604 @Test
3605 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
3606 final String policyXml = "<notification-policy version=\"1\">"
3607 + "<ranking></ranking>"
3608 + "<enabled_listeners>"
3609 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3610 + "</enabled_listeners>"
3611 + "<enabled_assistants>"
3612 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3613 + "</enabled_assistants>"
3614 + "<dnd_apps>"
3615 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3616 + "</dnd_apps>"
3617 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003618 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00003619 mService.readPolicyXml(
3620 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3621 true,
3622 10);
3623 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
3624 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
3625 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
3626 }
3627
3628 @Test
3629 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
3630 final String policyXml = "<notification-policy version=\"1\">"
3631 + "<ranking></ranking>"
3632 + "<enabled_listeners>"
3633 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3634 + "</enabled_listeners>"
3635 + "<enabled_assistants>"
3636 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3637 + "</enabled_assistants>"
3638 + "<dnd_apps>"
3639 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
3640 + "</dnd_apps>"
3641 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003642 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003643 mService.readPolicyXml(
3644 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3645 true,
3646 10);
3647 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3648 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3649 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3650 }
Beverlyd4f96492017-08-02 13:36:11 -04003651
3652 @Test
3653 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3654 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003655 mService.mZenModeHelper = mZenModeHelper;
3656 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003657 new Intent(Intent.ACTION_LOCALE_CHANGED));
3658
3659 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3660 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003661
3662 @Test
3663 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003664 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003665 final ApplicationInfo legacy = new ApplicationInfo();
3666 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3667 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3668 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003669 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3670 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003671 getContext().setMockPackageManager(mPackageManagerClient);
3672
3673 Notification.Builder nb = new Notification.Builder(mContext,
3674 NotificationChannel.DEFAULT_CHANNEL_ID)
3675 .setContentTitle("foo")
3676 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003677 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003678 .setPriority(Notification.PRIORITY_MIN);
3679
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003680 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3681 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynoldse61758a2020-06-10 10:26:44 -04003682 Binder.getCallingUid(), 0, nb.build(),
3683 UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003684
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003685 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3686 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003687 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003688
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003689 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003690 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003691
3692 nb = new Notification.Builder(mContext)
3693 .setContentTitle("foo")
3694 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003695 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003696 .setPriority(Notification.PRIORITY_MIN);
3697
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003698 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3699 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04003700 0, nb.build(), UserHandle.getUserHandleForUid(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003701
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003702 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3703 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003704 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3705 waitForIdle();
3706 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003707 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003708
3709 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003710 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003711 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3712 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003713
3714 @Test
3715 public void testStats_updatedOnDirectReply() throws Exception {
3716 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3717 mService.addNotification(r);
3718
3719 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3720 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Julia Reynolds24edc002020-01-29 16:35:32 -05003721 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.getSbn()));
Will Brockman9918db92020-03-06 16:48:39 -05003722
3723 assertEquals(1, mNotificationRecordLogger.numCalls());
3724 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DIRECT_REPLIED,
3725 mNotificationRecordLogger.event(0));
Julia Reynolds503ed942017-10-04 16:04:56 -04003726 }
3727
3728 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003729 public void testStats_updatedOnUserExpansion() throws Exception {
3730 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003731 mService.addNotification(r);
3732
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003733 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3734 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003735 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3736 eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003737 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003738
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003739 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3740 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds24edc002020-01-29 16:35:32 -05003741 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(true),
3742 eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003743 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Will Brockman9918db92020-03-06 16:48:39 -05003744
3745 assertEquals(2, mNotificationRecordLogger.numCalls());
3746 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_OPEN_USER,
3747 mNotificationRecordLogger.event(0));
3748 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_DETAIL_CLOSE_USER,
3749 mNotificationRecordLogger.event(1));
Julia Reynolds503ed942017-10-04 16:04:56 -04003750 }
3751
3752 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003753 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3754 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3755 mService.addNotification(r);
3756
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003757 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3758 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003759 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Julia Reynolds24edc002020-01-29 16:35:32 -05003760 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.getSbn()), eq(false),
3761 eq((true)));
Tony Makeda84a72018-11-19 17:01:32 +00003762
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003763 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3764 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003765 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003766 verify(mAssistants).notifyAssistantExpansionChangedLocked(
Julia Reynolds24edc002020-01-29 16:35:32 -05003767 eq(r.getSbn()), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003768 }
3769
3770 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003771 public void testStats_updatedOnViewSettings() throws Exception {
3772 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3773 mService.addNotification(r);
3774
3775 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3776 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3777 }
3778
3779 @Test
3780 public void testStats_updatedOnVisibilityChanged() throws Exception {
3781 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3782 mService.addNotification(r);
3783
Dieter Hsud39f0d52018-04-14 02:08:30 +08003784 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003785 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3786 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
Julia Reynolds24edc002020-01-29 16:35:32 -05003787 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(true));
Julia Reynolds503ed942017-10-04 16:04:56 -04003788 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3789 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3790 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
Julia Reynolds24edc002020-01-29 16:35:32 -05003791 verify(mAssistants).notifyAssistantVisibilityChangedLocked(eq(r.getSbn()), eq(false));
Julia Reynolds503ed942017-10-04 16:04:56 -04003792 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3793 }
3794
3795 @Test
3796 public void testStats_dismissalSurface() throws Exception {
3797 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Will Brockman4f0f9d22020-02-23 21:18:11 -05003798 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003799 mService.addNotification(r);
3800
Dieter Hsud39f0d52018-04-14 02:08:30 +08003801 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003802 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3803 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003804 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003805 waitForIdle();
3806
3807 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
Will Brockman75c60572020-01-31 10:30:27 -05003808
3809 // Using mService.addNotification() does not generate a NotificationRecordLogger log,
3810 // so we only get the cancel notification.
Will Brockman9918db92020-03-06 16:48:39 -05003811 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockman75c60572020-01-31 10:30:27 -05003812
Will Brockman75c60572020-01-31 10:30:27 -05003813 assertEquals(
3814 NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
Will Brockman9918db92020-03-06 16:48:39 -05003815 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05003816 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Julia Reynolds503ed942017-10-04 16:04:56 -04003817 }
3818
3819 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003820 public void testStats_dismissalSentiment() throws Exception {
3821 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3822 mService.addNotification(r);
3823
3824 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds24edc002020-01-29 16:35:32 -05003825 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
3826 r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003827 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3828 waitForIdle();
3829
3830 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3831 r.getStats().getDismissalSentiment());
3832 }
3833
3834 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003835 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003836 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3837 mService.addNotification(r);
3838 NotificationManagerService.WorkerHandler handler = mock(
3839 NotificationManagerService.WorkerHandler.class);
3840 mService.setHandler(handler);
3841
Julia Reynolds70aaea72018-07-13 13:38:34 -04003842 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3843
Julia Reynolds503ed942017-10-04 16:04:56 -04003844 Bundle signals = new Bundle();
3845 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003846 USER_SENTIMENT_NEGATIVE);
3847 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003848 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003849 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3850
3851 waitForIdle();
3852
3853 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3854 }
3855
3856 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003857 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003858 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3859 mService.addNotification(r);
3860 NotificationManagerService.WorkerHandler handler = mock(
3861 NotificationManagerService.WorkerHandler.class);
3862 mService.setHandler(handler);
3863
3864 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003865 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003866 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003867 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003868 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3869 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3870
3871 waitForIdle();
3872
3873 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3874 verify(handler, times(1)).scheduleCancelNotification(any());
3875 }
3876
3877 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003878 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3879 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3880 mService.addEnqueuedNotification(r);
3881 NotificationManagerService.WorkerHandler handler = mock(
3882 NotificationManagerService.WorkerHandler.class);
3883 mService.setHandler(handler);
3884 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3885
3886 Bundle signals = new Bundle();
3887 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3888 USER_SENTIMENT_NEGATIVE);
3889 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003890 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003891 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3892
3893 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3894 }
3895
3896 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003897 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003898 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3899 mService.addEnqueuedNotification(r);
3900 NotificationManagerService.WorkerHandler handler = mock(
3901 NotificationManagerService.WorkerHandler.class);
3902 mService.setHandler(handler);
3903 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3904
3905 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003906 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003907 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003908 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds27c0a962018-12-10 12:37:28 -05003909 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3910
3911 assertEquals(IMPORTANCE_LOW, r.getImportance());
3912 }
3913
3914 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003915 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3916 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3917 mService.addEnqueuedNotification(r);
3918 NotificationManagerService.WorkerHandler handler = mock(
3919 NotificationManagerService.WorkerHandler.class);
3920 mService.setHandler(handler);
3921 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3922
3923 Bundle signals = new Bundle();
3924 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3925 USER_SENTIMENT_NEGATIVE);
3926 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003927 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds70aaea72018-07-13 13:38:34 -04003928 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3929
3930 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3931
3932 waitForIdle();
3933
3934 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3935 }
3936
3937 @Test
3938 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3939 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3940 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003941 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3942
3943 Bundle signals = new Bundle();
3944 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3945 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003946 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003947 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds503ed942017-10-04 16:04:56 -04003948 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3949
3950 waitForIdle();
3951
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003952 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003953 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003954
3955 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003956 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3957 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3958 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003959 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003960
3961 Bundle signals = new Bundle();
3962 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003963 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003964 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003965 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003966 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3967
3968 waitForIdle();
3969
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003970 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003971 }
3972
3973 @Test
3974 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3975 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3976 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003977 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003978
3979 Bundle signals = new Bundle();
3980 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003981 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003982 Adjustment adjustment = new Adjustment(
Julia Reynolds24edc002020-01-29 16:35:32 -05003983 r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003984 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3985
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003986 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003987 }
3988
3989 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003990 public void testRestore() throws Exception {
3991 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003992 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003993 assertEquals(1, mService.countSystemChecks - systemChecks);
3994 }
3995
3996 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003997 public void testBackupEmptySound() throws Exception {
3998 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3999 channel.setSound(Uri.EMPTY, null);
4000
4001 XmlSerializer serializer = new FastXmlSerializer();
4002 ByteArrayOutputStream baos = new ByteArrayOutputStream();
4003 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
4004 channel.writeXmlForBackup(serializer, getContext());
4005
4006 XmlPullParser parser = Xml.newPullParser();
4007 parser.setInput(new BufferedInputStream(
4008 new ByteArrayInputStream(baos.toByteArray())), null);
4009 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
4010 restored.populateFromXmlForRestore(parser, getContext());
4011
4012 assertNull(restored.getSound());
4013 }
4014
4015 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05004016 public void testBackup() throws Exception {
4017 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04004018 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
4019 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05004020 mBinderService.getBackupPayload(1);
4021 assertEquals(1, mService.countSystemChecks - systemChecks);
4022 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004023
4024 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04004025 public void testEmptyVibration_noException() throws Exception {
4026 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
4027 channel.setVibrationPattern(new long[0]);
4028
4029 XmlSerializer serializer = new FastXmlSerializer();
4030 ByteArrayOutputStream baos = new ByteArrayOutputStream();
4031 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
4032 channel.writeXml(serializer);
4033 }
4034
4035 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004036 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004037 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05004038 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004039 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
4040 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004041 message1.setData("",
4042 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004043 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004044 message2.setData("",
4045 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004046
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004047 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004048 .setContentTitle("foo")
4049 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4050 .setStyle(new Notification.MessagingStyle("")
4051 .addMessage(message1)
4052 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004053 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
Julia Reynoldse61758a2020-06-10 10:26:44 -04004054 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
4055 null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004056
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004057 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004058 reset(mUgm);
4059 reset(mUgmInternal);
4060 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004061 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04004062 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004063 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004064 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004065 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004066 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
4067
4068 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004069 .setContentTitle("foo")
4070 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4071 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004072 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004073 PKG, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
4074 c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004075
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004076 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004077 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004078 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04004079 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004080 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
4081 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004082
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004083 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004084 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004085 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04004086 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004087 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004088 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004089
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004090 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004091 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06004092 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04004093 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07004094 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04004095 anyInt(), anyInt());
4096 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05004097
4098 @Test
Julia Reynoldsea58c202020-02-03 12:52:49 -05004099 public void updateUriPermissions_posterDoesNotOwnUri() throws Exception {
4100 NotificationChannel c = new NotificationChannel(
4101 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
4102 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
4103 Message message1 = new Message("", 0, "");
4104 message1.setData("",
4105 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
4106
4107 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
4108 .setContentTitle("foo")
4109 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4110 .setStyle(new Notification.MessagingStyle("")
4111 .addMessage(message1));
4112 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
Julia Reynoldse61758a2020-06-10 10:26:44 -04004113 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), UserHandle.getUserHandleForUid(mUid),
4114 null, 0), c);
Julia Reynoldsea58c202020-02-03 12:52:49 -05004115
4116 doThrow(new SecurityException("no access")).when(mUgm)
4117 .grantUriPermissionFromOwner(
4118 any(), anyInt(), any(), any(), anyInt(), anyInt(), anyInt());
4119
4120 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
4121 mService.updateUriPermissions(recordA, null, mContext.getPackageName(), USER_SYSTEM);
4122
4123 // yay, no crash
4124 }
4125
4126 @Test
Robin Leed107af62018-04-27 13:55:56 +02004127 public void testVisitUris() throws Exception {
4128 final Uri audioContents = Uri.parse("content://com.example/audio");
4129 final Uri backgroundImage = Uri.parse("content://com.example/background");
4130
4131 Bundle extras = new Bundle();
4132 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
4133 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
4134
4135 Notification n = new Notification.Builder(mContext, "a")
4136 .setContentTitle("notification with uris")
4137 .setSmallIcon(android.R.drawable.sym_def_app_icon)
4138 .addExtras(extras)
4139 .build();
4140
4141 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
4142 n.visitUris(visitor);
4143 verify(visitor, times(1)).accept(eq(audioContents));
4144 verify(visitor, times(1)).accept(eq(backgroundImage));
4145 }
4146
4147 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05004148 public void testSetNotificationPolicy_preP_setOldFields() {
4149 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4150 mService.mZenModeHelper = mZenModeHelper;
4151 NotificationManager.Policy userPolicy =
4152 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4153 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4154
4155 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4156 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
4157
4158 int expected = SUPPRESSED_EFFECT_BADGE
4159 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04004160 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
4161 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05004162 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
4163
4164 assertEquals(expected, actual);
4165 }
4166
4167 @Test
4168 public void testSetNotificationPolicy_preP_setNewFields() {
4169 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4170 mService.mZenModeHelper = mZenModeHelper;
4171 NotificationManager.Policy userPolicy =
4172 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4173 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4174
4175 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4176 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
4177
4178 int expected = SUPPRESSED_EFFECT_BADGE;
4179 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
4180
4181 assertEquals(expected, actual);
4182 }
4183
4184 @Test
4185 public void testSetNotificationPolicy_preP_setOldNewFields() {
4186 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4187 mService.mZenModeHelper = mZenModeHelper;
4188 NotificationManager.Policy userPolicy =
4189 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4190 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4191
4192 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4193 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
4194
4195 int expected =
4196 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
4197 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
4198
4199 assertEquals(expected, actual);
4200 }
4201
4202 @Test
4203 public void testSetNotificationPolicy_P_setOldFields() {
4204 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4205 mService.mZenModeHelper = mZenModeHelper;
4206 NotificationManager.Policy userPolicy =
4207 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4208 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4209
4210 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4211 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
4212
4213 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
4214 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
4215 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4216 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4217
4218 assertEquals(expected, actual);
4219 }
4220
4221 @Test
4222 public void testSetNotificationPolicy_P_setNewFields() {
4223 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4224 mService.mZenModeHelper = mZenModeHelper;
4225 NotificationManager.Policy userPolicy =
4226 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4227 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4228
4229 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4230 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
4231 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4232
4233 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
4234 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
4235 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4236 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4237
4238 assertEquals(expected, actual);
4239 }
4240
4241 @Test
4242 public void testSetNotificationPolicy_P_setOldNewFields() {
4243 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
4244 mService.mZenModeHelper = mZenModeHelper;
4245 NotificationManager.Policy userPolicy =
4246 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
4247 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
4248
4249 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
4250 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
4251
4252 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
4253 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4254
4255 assertEquals(expected, actual);
4256
4257 appPolicy = new NotificationManager.Policy(0, 0, 0,
4258 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
4259 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
4260
4261 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
4262 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
4263 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
4264
4265 assertEquals(expected, actual);
4266 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05004267
4268 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04004269 public void testVisualDifference_foreground() {
4270 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4271 .setContentTitle("foo");
4272 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004273 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04004274 NotificationRecord r1 =
4275 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4276
4277 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4278 .setFlag(FLAG_FOREGROUND_SERVICE, true)
4279 .setContentTitle("bar");
4280 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004281 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04004282 NotificationRecord r2 =
4283 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4284
4285 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4286 }
4287
4288 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004289 public void testVisualDifference_diffTitle() {
4290 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4291 .setContentTitle("foo");
4292 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004293 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004294 NotificationRecord r1 =
4295 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4296
4297 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4298 .setContentTitle("bar");
4299 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004300 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004301 NotificationRecord r2 =
4302 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4303
4304 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4305 }
4306
4307 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004308 public void testVisualDifference_inboxStyle() {
4309 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4310 .setStyle(new Notification.InboxStyle()
4311 .addLine("line1").addLine("line2"));
4312 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004313 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004314 NotificationRecord r1 =
4315 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4316
4317 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4318 .setStyle(new Notification.InboxStyle()
4319 .addLine("line1").addLine("line2_changed"));
4320 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004321 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004322 NotificationRecord r2 =
4323 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4324
4325 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
4326
4327 Notification.Builder nb3 = new Notification.Builder(mContext, "")
4328 .setStyle(new Notification.InboxStyle()
4329 .addLine("line1"));
4330 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004331 nb3.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004332 NotificationRecord r3 =
4333 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
4334
4335 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
4336
4337 Notification.Builder nb4 = new Notification.Builder(mContext, "")
4338 .setStyle(new Notification.InboxStyle()
4339 .addLine("line1").addLine("line2").addLine("line3"));
4340 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004341 nb4.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004342 NotificationRecord r4 =
4343 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
4344
4345 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
4346
4347 Notification.Builder nb5 = new Notification.Builder(mContext, "")
4348 .setContentText("not an inbox");
4349 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004350 nb5.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004351 NotificationRecord r5 =
4352 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
4353
4354 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
4355 }
4356
4357 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004358 public void testVisualDifference_diffText() {
4359 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4360 .setContentText("foo");
4361 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004362 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004363 NotificationRecord r1 =
4364 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4365
4366 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4367 .setContentText("bar");
4368 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004369 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004370 NotificationRecord r2 =
4371 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4372
4373 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4374 }
4375
4376 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004377 public void testVisualDifference_sameText() {
4378 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4379 .setContentText("foo");
4380 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004381 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004382 NotificationRecord r1 =
4383 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4384
4385 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4386 .setContentText("foo");
4387 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004388 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004389 NotificationRecord r2 =
4390 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4391
4392 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4393 }
4394
4395 @Test
4396 public void testVisualDifference_sameTextButStyled() {
4397 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4398 .setContentText(Html.fromHtml("<b>foo</b>"));
4399 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004400 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004401 NotificationRecord r1 =
4402 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4403
4404 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4405 .setContentText(Html.fromHtml("<b>foo</b>"));
4406 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004407 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004408 NotificationRecord r2 =
4409 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4410
4411 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4412 }
4413
4414 @Test
4415 public void testVisualDifference_diffTextButStyled() {
4416 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4417 .setContentText(Html.fromHtml("<b>foo</b>"));
4418 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004419 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004420 NotificationRecord r1 =
4421 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4422
4423 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4424 .setContentText(Html.fromHtml("<b>bar</b>"));
4425 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004426 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004427 NotificationRecord r2 =
4428 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4429
4430 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4431 }
4432
4433 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05004434 public void testVisualDifference_diffProgress() {
4435 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4436 .setProgress(100, 90, false);
4437 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004438 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004439 NotificationRecord r1 =
4440 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4441
4442 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4443 .setProgress(100, 100, false);
4444 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004445 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004446 NotificationRecord r2 =
4447 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4448
4449 assertTrue(mService.isVisuallyInterruptive(r1, r2));
4450 }
4451
4452 @Test
4453 public void testVisualDifference_diffProgressNotDone() {
4454 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4455 .setProgress(100, 90, false);
4456 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004457 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004458 NotificationRecord r1 =
4459 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4460
4461 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4462 .setProgress(100, 91, false);
4463 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004464 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds7217dc92018-03-07 12:12:09 -05004465 NotificationRecord r2 =
4466 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4467
4468 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4469 }
Beverly5a20a5e2018-03-06 15:02:44 -05004470
4471 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04004472 public void testVisualDifference_sameProgressStillDone() {
4473 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4474 .setProgress(100, 100, false);
4475 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004476 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004477 NotificationRecord r1 =
4478 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4479
4480 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4481 .setProgress(100, 100, false);
4482 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004483 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Dan Sandler7d67bd42018-05-15 14:06:38 -04004484 NotificationRecord r2 =
4485 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4486
4487 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4488 }
4489
4490 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004491 public void testVisualDifference_summary() {
4492 Notification.Builder nb1 = new Notification.Builder(mContext, "")
4493 .setGroup("bananas")
4494 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4495 .setContentText("foo");
4496 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004497 nb1.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004498 NotificationRecord r1 =
4499 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
4500
4501 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4502 .setGroup("bananas")
4503 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4504 .setContentText("bar");
4505 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004506 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04004507 NotificationRecord r2 =
4508 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4509
4510 assertFalse(mService.isVisuallyInterruptive(r1, r2));
4511 }
4512
4513 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04004514 public void testVisualDifference_summaryNewNotification() {
4515 Notification.Builder nb2 = new Notification.Builder(mContext, "")
4516 .setGroup("bananas")
4517 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
4518 .setContentText("bar");
4519 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004520 nb2.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds760fa762018-06-19 15:39:23 -04004521 NotificationRecord r2 =
4522 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
4523
4524 assertFalse(mService.isVisuallyInterruptive(null, r2));
4525 }
4526
4527 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05004528 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
4529 // post 2 notification from this package
4530 final NotificationRecord notif1 = generateNotificationRecord(
4531 mTestNotificationChannel, 1, null, true);
4532 final NotificationRecord notif2 = generateNotificationRecord(
4533 mTestNotificationChannel, 2, null, false);
4534 mService.addNotification(notif1);
4535 mService.addNotification(notif2);
4536
4537 // on broadcast, hide the 2 notifications
4538 mService.simulatePackageSuspendBroadcast(true, PKG);
4539 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
4540 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4541 assertEquals(2, captorHide.getValue().size());
4542
4543 // on broadcast, unhide the 2 notifications
4544 mService.simulatePackageSuspendBroadcast(false, PKG);
4545 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
4546 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4547 assertEquals(2, captorUnhide.getValue().size());
4548 }
4549
4550 @Test
4551 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
4552 // post 2 notification from this package
4553 final NotificationRecord notif1 = generateNotificationRecord(
4554 mTestNotificationChannel, 1, null, true);
4555 final NotificationRecord notif2 = generateNotificationRecord(
4556 mTestNotificationChannel, 2, null, false);
4557 mService.addNotification(notif1);
4558 mService.addNotification(notif2);
4559
4560 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4561 mService.simulatePackageSuspendBroadcast(true, "test_package");
4562 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4563 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4564 assertEquals(0, captor.getValue().size());
4565 }
Kristian Monsen05f34792018-04-09 10:27:16 +02004566
4567 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004568 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
4569 // Post 2 notifications from 2 packages
4570 NotificationRecord pkgA = new NotificationRecord(mContext,
4571 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4572 mService.addNotification(pkgA);
4573 NotificationRecord pkgB = new NotificationRecord(mContext,
4574 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4575 mService.addNotification(pkgB);
4576
4577 // on broadcast, hide one of the packages
4578 mService.simulatePackageDistractionBroadcast(
4579 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
4580 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
4581 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
4582 assertEquals(1, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004583 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004584
4585 // on broadcast, unhide the package
4586 mService.simulatePackageDistractionBroadcast(
4587 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
4588 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
4589 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
4590 assertEquals(1, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004591 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004592 }
4593
4594 @Test
4595 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
4596 // Post 2 notifications from 2 packages
4597 NotificationRecord pkgA = new NotificationRecord(mContext,
4598 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
4599 mService.addNotification(pkgA);
4600 NotificationRecord pkgB = new NotificationRecord(mContext,
4601 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
4602 mService.addNotification(pkgB);
4603
4604 // on broadcast, hide one of the packages
4605 mService.simulatePackageDistractionBroadcast(
4606 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
4607 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004608
4609 // should be called only once.
4610 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004611 assertEquals(2, captorHide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004612 assertEquals("a", captorHide.getValue().get(0).getSbn().getPackageName());
4613 assertEquals("b", captorHide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004614
4615 // on broadcast, unhide the package
4616 mService.simulatePackageDistractionBroadcast(
4617 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
4618 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09004619
4620 // should be called only once.
4621 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004622 assertEquals(2, captorUnhide.getValue().size());
Julia Reynolds24edc002020-01-29 16:35:32 -05004623 assertEquals("a", captorUnhide.getValue().get(0).getSbn().getPackageName());
4624 assertEquals("b", captorUnhide.getValue().get(1).getSbn().getPackageName());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05004625 }
4626
4627 @Test
4628 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
4629 // post notification from this package
4630 final NotificationRecord notif1 = generateNotificationRecord(
4631 mTestNotificationChannel, 1, null, true);
4632 mService.addNotification(notif1);
4633
4634 // on broadcast, nothing is hidden since no notifications are of package "test_package"
4635 mService.simulatePackageDistractionBroadcast(
4636 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
4637 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
4638 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
4639 assertEquals(0, captor.getValue().size());
4640 }
4641
4642 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004643 public void testCanUseManagedServicesNullPkg() {
4644 assertEquals(true, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004645 }
4646
Kristian Monsen05f34792018-04-09 10:27:16 +02004647
4648 @Test
Rajeev Kumarbc79dcd2020-02-04 19:54:30 -08004649 public void testCanUseManagedServicesNoValidPkg() {
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004650 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4651 }
4652
4653 @Test
4654 public void testCanUseManagedServices_hasPermission() throws Exception {
4655 when(mPackageManager.checkPermission("perm", "pkg", 0))
4656 .thenReturn(PackageManager.PERMISSION_GRANTED);
4657
4658 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4659 }
4660
4661 @Test
4662 public void testCanUseManagedServices_noPermission() throws Exception {
4663 when(mPackageManager.checkPermission("perm", "pkg", 0))
4664 .thenReturn(PackageManager.PERMISSION_DENIED);
4665
4666 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4667 }
4668
4669 @Test
4670 public void testCanUseManagedServices_permDoesNotMatter() {
4671 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004672 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004673
4674 @Test
4675 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4676 final NotificationRecord r = generateNotificationRecord(
4677 mTestNotificationChannel, 1, null, true);
4678 r.setTextChanged(true);
4679 mService.addNotification(r);
4680
4681 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4682 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4683 new NotificationVisibility[]{});
4684
4685 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4686 }
4687
4688 @Test
Will Brockmand3d49332020-02-10 19:43:03 -05004689 public void testOnNotificationVisibilityChanged_triggersVisibilityLog() {
4690 final NotificationRecord r = generateNotificationRecord(
4691 mTestNotificationChannel, 1, null, true);
4692 r.setTextChanged(true);
Will Brockman4f0f9d22020-02-23 21:18:11 -05004693 r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004694 mService.addNotification(r);
4695
4696 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4697 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4698 new NotificationVisibility[]{});
4699
Will Brockman9918db92020-03-06 16:48:39 -05004700 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004701 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN,
Will Brockman9918db92020-03-06 16:48:39 -05004702 mNotificationRecordLogger.event(0));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004703 assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004704
4705 mService.mNotificationDelegate.onNotificationVisibilityChanged(
4706 new NotificationVisibility[]{},
4707 new NotificationVisibility[]
4708 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)}
4709 );
4710
Will Brockman9918db92020-03-06 16:48:39 -05004711 assertEquals(2, mNotificationRecordLogger.numCalls());
Will Brockmand3d49332020-02-10 19:43:03 -05004712 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE,
Will Brockman9918db92020-03-06 16:48:39 -05004713 mNotificationRecordLogger.event(1));
Will Brockman4f0f9d22020-02-23 21:18:11 -05004714 assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId());
Will Brockmand3d49332020-02-10 19:43:03 -05004715 }
4716
4717 @Test
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004718 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4719 throws RemoteException {
4720 final NotificationRecord r = generateNotificationRecord(
4721 mTestNotificationChannel, 1, null, true);
4722 r.setTextChanged(true);
4723 mService.addNotification(r);
4724
4725 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4726
4727 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4728 }
4729
4730 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004731 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004732 throws RemoteException {
4733 final NotificationRecord r = generateNotificationRecord(
4734 mTestNotificationChannel, 1, null, true);
4735 r.setInterruptive(true);
4736 mService.addNotification(r);
4737
4738 mService.maybeRecordInterruptionLocked(r);
4739 mService.maybeRecordInterruptionLocked(r);
4740
4741 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4742 anyString(), anyString(), anyInt());
Julia Reynoldsfd9f8342020-03-06 09:36:00 -05004743 verify(mHistoryManager, times(1)).addNotification(any());
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004744 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004745
4746 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004747 public void testBubble() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004748 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4749 assertFalse(mBinderService.areBubblesAllowed(PKG));
4750 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4751 BUBBLE_PREFERENCE_NONE);
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004752 }
4753
4754 @Test
Mady Mellora92268c2020-03-09 17:25:08 -07004755 public void testUserApprovedBubblesForPackageSelected() throws Exception {
4756 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_SELECTED);
4757 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4758 BUBBLE_PREFERENCE_SELECTED);
4759 }
4760
4761 @Test
4762 public void testUserApprovedBubblesForPackageAll() throws Exception {
4763 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_ALL);
4764 assertTrue(mBinderService.areBubblesAllowed(PKG));
4765 assertEquals(mBinderService.getBubblePreferenceForPackage(PKG, mUid),
4766 BUBBLE_PREFERENCE_ALL);
Mady Mellor9db685a2019-01-23 13:23:37 -08004767 }
4768
4769 @Test
4770 public void testUserRejectsBubblesForPackage() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07004771 mBinderService.setBubblesAllowed(PKG, mUid, BUBBLE_PREFERENCE_NONE);
4772 assertFalse(mBinderService.areBubblesAllowed(PKG));
Mady Mellor9db685a2019-01-23 13:23:37 -08004773 }
4774
4775 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004776 public void testIsCallerInstantApp_primaryUser() throws Exception {
4777 ApplicationInfo info = new ApplicationInfo();
4778 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4779 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004780 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004781
Julia Reynolds268647a2018-10-25 16:54:27 -04004782 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004783
4784 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004785 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004786 }
4787
4788 @Test
4789 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4790 ApplicationInfo info = new ApplicationInfo();
4791 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4792 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4793 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004794 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004795
Julia Reynolds268647a2018-10-25 16:54:27 -04004796 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004797 }
4798
4799 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004800 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4801 ApplicationInfo info = new ApplicationInfo();
4802 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004803 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004804 .thenReturn(info);
4805 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4806
4807 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4808
4809 info.privateFlags = 0;
4810 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4811 }
4812
4813 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004814 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4815 ApplicationInfo info = new ApplicationInfo();
4816 info.uid = Binder.getCallingUid();
4817 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4818 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4819
4820 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4821
4822 assertEquals(info.uid, actualUid);
4823 }
4824
4825 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004826 public void testResolveNotificationUid_sameApp() throws Exception {
4827 ApplicationInfo info = new ApplicationInfo();
4828 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004829 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004830
4831 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4832
4833 assertEquals(info.uid, actualUid);
4834 }
4835
4836 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004837 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004838 ApplicationInfo info = new ApplicationInfo();
4839 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004840 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004841
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004842 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4843
4844 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004845 }
4846
4847 @Test
4848 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4849 ApplicationInfo info = new ApplicationInfo();
4850 info.uid = 1356347;
4851 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4852
4853 try {
4854 mService.resolveNotificationUid("caller", "caller", 9, 0);
4855 fail("Incorrect uid didn't throw security exception");
4856 } catch (SecurityException e) {
4857 // yay
4858 }
4859 }
4860
4861 @Test
4862 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4863 int expectedUid = 123;
4864
4865 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4866 mService.setPreferencesHelper(mPreferencesHelper);
4867 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4868 .thenReturn(true);
4869
4870 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4871 }
4872
4873 @Test
4874 public void testResolveNotificationUid_androidAllowed() throws Exception {
4875 int expectedUid = 123;
4876
4877 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4878 // no delegate
4879
4880 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4881 }
4882
4883 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004884 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4885 final String notReal = "NOT REAL";
4886 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4887 PackageManager.NameNotFoundException.class);
4888 ApplicationInfo ai = new ApplicationInfo();
4889 ai.uid = -1;
4890 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4891
Julia Reynolds24edc002020-01-29 16:35:32 -05004892 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004893 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004894 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4895 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004896 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4897 fail("can't post notifications for nonexistent packages, even if you exist");
4898 } catch (SecurityException e) {
4899 // yay
4900 }
4901 }
4902
4903 @Test
4904 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4905 final String notReal = "NOT REAL";
4906 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4907 PackageManager.NameNotFoundException.class);
4908 ApplicationInfo ai = new ApplicationInfo();
4909 ai.uid = -1;
4910 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4911
4912 // unlike the post case, ignore instead of throwing
Julia Reynolds24edc002020-01-29 16:35:32 -05004913 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004914
4915 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4916 sbn.getId(), sbn.getUserId());
4917 }
4918
4919 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004920 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4921 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4922 // no delegate
4923
4924 try {
4925 mService.resolveNotificationUid("caller", "target", 9, 0);
4926 fail("Incorrect uid didn't throw security exception");
4927 } catch (SecurityException e) {
4928 // yay
4929 }
4930 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004931
4932 @Test
4933 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4934 Notification n = new Notification.Builder(mContext, "").build();
4935 n.flags |= FLAG_FOREGROUND_SERVICE;
4936
4937 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004938 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds564273f2018-09-13 15:53:11 -04004939 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4940
4941 mService.addEnqueuedNotification(r);
4942
4943 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004944 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004945
4946 waitForIdle();
4947
4948 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4949 }
4950
4951 @Test
4952 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4953 Notification n = new Notification.Builder(mContext, "").build();
4954 n.flags |= FLAG_FOREGROUND_SERVICE;
4955
4956 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04004957 n, UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds564273f2018-09-13 15:53:11 -04004958 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4959
4960 mService.addNotification(r);
4961
4962 mInternalService.removeForegroundServiceFlagFromNotification(
Julia Reynolds24edc002020-01-29 16:35:32 -05004963 PKG, r.getSbn().getId(), r.getSbn().getUserId());
Julia Reynolds564273f2018-09-13 15:53:11 -04004964
4965 waitForIdle();
4966
4967 ArgumentCaptor<NotificationRecord> captor =
4968 ArgumentCaptor.forClass(NotificationRecord.class);
4969 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4970
4971 assertEquals(0, captor.getValue().getNotification().flags);
4972 }
Beverly58b24532018-10-02 09:08:23 -04004973
4974 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004975 public void testAllowForegroundCustomToasts() throws Exception {
Beverly58b24532018-10-02 09:08:23 -04004976 final String testPackage = "testPackageName";
4977 assertEquals(0, mService.mToastQueue.size());
4978 mService.isSystemUid = false;
4979
4980 // package is not suspended
4981 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4982 .thenReturn(false);
4983
4984 // notifications from this package are blocked by the user
4985 mService.setPreferencesHelper(mPreferencesHelper);
4986 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4987
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00004988 setAppInForegroundForToasts(mUid, true);
Beverly58b24532018-10-02 09:08:23 -04004989
4990 // enqueue toast -> toast should still enqueue
Bernardo Rufino52af6db2019-12-20 18:26:07 +00004991 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04004992 new TestableToastCallback(), 2000, 0);
4993 assertEquals(1, mService.mToastQueue.size());
4994 }
4995
4996 @Test
Bernardo Rufino18725b62020-01-21 14:12:43 +00004997 public void testDisallowBackgroundCustomToasts() throws Exception {
4998 final String testPackage = "testPackageName";
4999 assertEquals(0, mService.mToastQueue.size());
5000 mService.isSystemUid = false;
5001
5002 // package is not suspended
5003 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5004 .thenReturn(false);
5005
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00005006 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00005007
5008 // enqueue toast -> no toasts enqueued
5009 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
5010 new TestableToastCallback(), 2000, 0);
5011 assertEquals(0, mService.mToastQueue.size());
5012 }
5013
5014 @Test
5015 public void testAllowForegroundTextToasts() throws Exception {
5016 final String testPackage = "testPackageName";
5017 assertEquals(0, mService.mToastQueue.size());
5018 mService.isSystemUid = false;
5019
5020 // package is not suspended
5021 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5022 .thenReturn(false);
5023
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00005024 setAppInForegroundForToasts(mUid, true);
Bernardo Rufino18725b62020-01-21 14:12:43 +00005025
5026 // enqueue toast -> toast should still enqueue
5027 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
5028 "Text", 2000, 0, null);
5029 assertEquals(1, mService.mToastQueue.size());
5030 }
5031
5032 @Test
5033 public void testAllowBackgroundTextToasts() throws Exception {
5034 final String testPackage = "testPackageName";
5035 assertEquals(0, mService.mToastQueue.size());
5036 mService.isSystemUid = false;
5037
5038 // package is not suspended
5039 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5040 .thenReturn(false);
5041
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00005042 setAppInForegroundForToasts(mUid, false);
Bernardo Rufino18725b62020-01-21 14:12:43 +00005043
5044 // enqueue toast -> toast should still enqueue
5045 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
5046 "Text", 2000, 0, null);
5047 assertEquals(1, mService.mToastQueue.size());
5048 }
5049
5050 @Test
5051 public void testTextToastsCallStatusBar() throws Exception {
5052 final String testPackage = "testPackageName";
5053 assertEquals(0, mService.mToastQueue.size());
5054 mService.isSystemUid = false;
5055
5056 // package is not suspended
5057 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5058 .thenReturn(false);
5059
5060 // enqueue toast -> no toasts enqueued
5061 ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
5062 "Text", 2000, 0, null);
Bernardo Rufino78f5d832020-04-03 11:50:23 +01005063 verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
Bernardo Rufino18725b62020-01-21 14:12:43 +00005064 }
5065
5066 @Test
Beverly58b24532018-10-02 09:08:23 -04005067 public void testDisallowToastsFromSuspendedPackages() throws Exception {
5068 final String testPackage = "testPackageName";
5069 assertEquals(0, mService.mToastQueue.size());
5070 mService.isSystemUid = false;
5071
5072 // package is suspended
5073 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5074 .thenReturn(true);
5075
5076 // notifications from this package are NOT blocked by the user
5077 mService.setPreferencesHelper(mPreferencesHelper);
5078 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
5079
5080 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00005081 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04005082 new TestableToastCallback(), 2000, 0);
5083 assertEquals(0, mService.mToastQueue.size());
5084 }
5085
5086 @Test
5087 public void testDisallowToastsFromBlockedApps() throws Exception {
5088 final String testPackage = "testPackageName";
5089 assertEquals(0, mService.mToastQueue.size());
5090 mService.isSystemUid = false;
5091
5092 // package is not suspended
5093 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5094 .thenReturn(false);
5095
5096 // notifications from this package are blocked by the user
5097 mService.setPreferencesHelper(mPreferencesHelper);
5098 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
5099
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00005100 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04005101
5102 // enqueue toast -> no toasts enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00005103 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04005104 new TestableToastCallback(), 2000, 0);
5105 assertEquals(0, mService.mToastQueue.size());
5106 }
5107
5108 @Test
5109 public void testAlwaysAllowSystemToasts() throws Exception {
5110 final String testPackage = "testPackageName";
5111 assertEquals(0, mService.mToastQueue.size());
5112 mService.isSystemUid = true;
5113
5114 // package is suspended
5115 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
5116 .thenReturn(true);
5117
5118 // notifications from this package ARE blocked by the user
5119 mService.setPreferencesHelper(mPreferencesHelper);
5120 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
5121
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00005122 setAppInForegroundForToasts(mUid, false);
Beverly58b24532018-10-02 09:08:23 -04005123
5124 // enqueue toast -> system toast can still be enqueued
Bernardo Rufino52af6db2019-12-20 18:26:07 +00005125 ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
Beverly58b24532018-10-02 09:08:23 -04005126 new TestableToastCallback(), 2000, 0);
5127 assertEquals(1, mService.mToastQueue.size());
5128 }
Tony Mak29996702018-11-26 16:23:34 +00005129
Bernardo Rufinoe6cb3102020-03-06 20:33:11 +00005130 private void setAppInForegroundForToasts(int uid, boolean inForeground) {
5131 int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
5132 when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);
5133 when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground);
5134 }
5135
Tony Mak29996702018-11-26 16:23:34 +00005136 @Test
Alex Mang509e5542020-01-03 13:06:40 -08005137 public void testOnPanelRevealedAndHidden() {
5138 int items = 5;
5139 mService.mNotificationDelegate.onPanelRevealed(false, items);
5140 verify(mAssistants, times(1)).onPanelRevealed(eq(items));
5141
5142 mService.mNotificationDelegate.onPanelHidden();
5143 verify(mAssistants, times(1)).onPanelHidden();
Will Brockman9918db92020-03-06 16:48:39 -05005144
5145 assertEquals(2, mNotificationRecordLogger.numCalls());
5146 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_OPEN,
5147 mNotificationRecordLogger.event(0));
5148 assertEquals(NotificationRecordLogger.NotificationPanelEvent.NOTIFICATION_PANEL_CLOSE,
5149 mNotificationRecordLogger.event(1));
Alex Mang509e5542020-01-03 13:06:40 -08005150 }
5151
5152 @Test
Tony Mak29996702018-11-26 16:23:34 +00005153 public void testOnNotificationSmartReplySent() {
5154 final int replyIndex = 2;
5155 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00005156 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00005157 final boolean generatedByAssistant = true;
5158
5159 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00005160 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00005161 mService.addNotification(r);
5162
5163 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00005164 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
5165 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00005166 verify(mAssistants).notifyAssistantSuggestedReplySent(
Julia Reynolds24edc002020-01-29 16:35:32 -05005167 eq(r.getSbn()), eq(reply), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05005168 assertEquals(1, mNotificationRecordLogger.numCalls());
5169 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED,
5170 mNotificationRecordLogger.event(0));
Tony Mak29996702018-11-26 16:23:34 +00005171 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00005172
5173 @Test
5174 public void testOnNotificationActionClick() {
5175 final int actionIndex = 2;
5176 final Notification.Action action =
5177 new Notification.Action.Builder(null, "text", null).build();
5178 final boolean generatedByAssistant = false;
5179
5180 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5181 mService.addNotification(r);
5182
5183 NotificationVisibility notificationVisibility =
5184 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
5185 mService.mNotificationDelegate.onNotificationActionClick(
5186 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
5187 generatedByAssistant);
5188 verify(mAssistants).notifyAssistantActionClicked(
Julia Reynolds24edc002020-01-29 16:35:32 -05005189 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
Will Brockman9918db92020-03-06 16:48:39 -05005190
5191 assertEquals(1, mNotificationRecordLogger.numCalls());
Will Brockman2a2c0c92020-05-04 13:58:28 -04005192 assertEquals(
5193 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ACTION_CLICKED_2,
5194 mNotificationRecordLogger.event(0));
5195 }
5196
5197 @Test
5198 public void testOnAssistantNotificationActionClick() {
5199 final int actionIndex = 1;
5200 final Notification.Action action =
5201 new Notification.Action.Builder(null, "text", null).build();
5202 final boolean generatedByAssistant = true;
5203
5204 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5205 mService.addNotification(r);
5206
5207 NotificationVisibility notificationVisibility =
5208 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
5209 mService.mNotificationDelegate.onNotificationActionClick(
5210 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
5211 generatedByAssistant);
5212 verify(mAssistants).notifyAssistantActionClicked(
5213 eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
5214
5215 assertEquals(1, mNotificationRecordLogger.numCalls());
5216 assertEquals(
5217 NotificationRecordLogger.NotificationEvent.NOTIFICATION_ASSIST_ACTION_CLICKED_1,
Will Brockman9918db92020-03-06 16:48:39 -05005218 mNotificationRecordLogger.event(0));
Tony Mak7d4b3a52018-11-27 17:29:36 +00005219 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00005220
5221 @Test
5222 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
5223 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5224 mService.addNotification(r);
5225
Gustav Senntona8e38aa2019-01-22 14:55:39 +00005226 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5227 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00005228 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
5229 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
5230 };
5231 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
5232 new NotificationVisibility[0]);
5233
5234 assertEquals(1, mService.countLogSmartSuggestionsVisible);
5235 }
5236
5237 @Test
5238 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
5239 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5240 mService.addNotification(r);
5241
Gustav Senntona8e38aa2019-01-22 14:55:39 +00005242 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
5243 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00005244
5245 assertEquals(0, mService.countLogSmartSuggestionsVisible);
5246 }
5247
5248 @Test
5249 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
5250 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5251 mService.addNotification(r);
5252
Julia Reynolds95334132018-12-19 11:15:35 -05005253 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00005254 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
5255 };
5256 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
5257 new NotificationVisibility[0]);
5258
5259 assertEquals(0, mService.countLogSmartSuggestionsVisible);
5260 }
Julia Reynolds95334132018-12-19 11:15:35 -05005261
Colin Cross5ea7fb72019-12-18 17:16:36 -08005262 @Test
Julia Reynolds95334132018-12-19 11:15:35 -05005263 public void testReportSeen_delegated() {
5264 Notification.Builder nb =
5265 new Notification.Builder(mContext, mTestNotificationChannel.getId())
5266 .setContentTitle("foo")
5267 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5268
5269 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005270 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds95334132018-12-19 11:15:35 -05005271 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5272
5273 mService.reportSeen(r);
5274 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
5275
5276 }
5277
5278 @Test
5279 public void testReportSeen_notDelegated() {
5280 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5281
5282 mService.reportSeen(r);
5283 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
5284 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005285
5286 @Test
5287 public void testNotificationStats_notificationError() {
5288 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
5289 mService.addNotification(r);
5290
Julia Reynolds24edc002020-01-29 16:35:32 -05005291 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.getSbn().getId(),
5292 r.getSbn().getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005293 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04005294 UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005295 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5296 mService.addEnqueuedNotification(update);
Julia Reynolds24edc002020-01-29 16:35:32 -05005297 assertNull(update.getSbn().getNotification().getSmallIcon());
Julia Reynolds3207e2f2018-12-20 09:39:53 -05005298
5299 NotificationManagerService.PostNotificationRunnable runnable =
5300 mService.new PostNotificationRunnable(update.getKey());
5301 runnable.run();
5302 waitForIdle();
5303
5304 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
5305 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
5306 assertNotNull(captor.getValue());
5307 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005308
5309 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005310 public void testCanNotifyAsUser_crossUser() throws Exception {
5311 // same user no problem
5312 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
5313
5314 // cross user, no permission, problem
5315 try {
5316 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5317 fail("Should not be callable cross user without cross user permission");
5318 } catch (SecurityException e) {
5319 // good
5320 }
5321
5322 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005323 enableInteractAcrossUsers();
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04005324 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
5325 }
5326
5327 @Test
Julia Reynoldse61758a2020-06-10 10:26:44 -04005328 public void testGetNotificationChannels_crossUser() throws Exception {
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005329 // same user no problem
5330 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
5331
5332 // cross user, no permission, problem
5333 try {
5334 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5335 fail("Should not be callable cross user without cross user permission");
5336 } catch (SecurityException e) {
5337 // good
5338 }
5339
5340 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005341 enableInteractAcrossUsers();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04005342 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
5343 }
5344
5345 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00005346 public void setDefaultAssistantForUser_fromConfigXml() {
5347 clearDeviceConfig();
5348 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04005349 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005350 when(mResources
5351 .getString(
5352 com.android.internal.R.string.config_defaultAssistantAccessComponent))
5353 .thenReturn(xmlConfig.flattenToString());
5354 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005355 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
5356 .thenReturn(components);
5357 when(mAssistants.getDefaultComponents())
5358 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00005359 mService.setNotificationAssistantAccessGrantedCallback(
5360 mNotificationAssistantAccessGrantedCallback);
5361
Jay Aliomer4204f252019-08-26 11:36:53 -04005362
Tony Mak9a3c1f12019-03-04 16:04:42 +00005363 mService.setDefaultAssistantForUser(0);
5364
5365 verify(mNotificationAssistantAccessGrantedCallback)
5366 .onGranted(eq(xmlConfig), eq(0), eq(true));
5367 }
5368
5369 @Test
5370 public void setDefaultAssistantForUser_fromDeviceConfig() {
5371 ComponentName xmlConfig = new ComponentName("xml", "config");
5372 ComponentName deviceConfig = new ComponentName("device", "config");
5373 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5374 when(mResources
5375 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5376 .thenReturn(xmlConfig.flattenToString());
5377 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04005378 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00005379 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04005380 when(mAssistants.getDefaultComponents())
5381 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005382 mService.setNotificationAssistantAccessGrantedCallback(
5383 mNotificationAssistantAccessGrantedCallback);
5384
5385 mService.setDefaultAssistantForUser(0);
5386
5387 verify(mNotificationAssistantAccessGrantedCallback)
5388 .onGranted(eq(deviceConfig), eq(0), eq(true));
5389 }
5390
5391 @Test
5392 public void setDefaultAssistantForUser_deviceConfigInvalid() {
5393 ComponentName xmlConfig = new ComponentName("xml", "config");
5394 ComponentName deviceConfig = new ComponentName("device", "config");
5395 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
5396 when(mResources
5397 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
5398 .thenReturn(xmlConfig.flattenToString());
5399 when(mContext.getResources()).thenReturn(mResources);
5400 // Only xmlConfig is valid, deviceConfig is not.
5401 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04005402 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
5403 when(mAssistants.getDefaultComponents())
5404 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00005405 mService.setNotificationAssistantAccessGrantedCallback(
5406 mNotificationAssistantAccessGrantedCallback);
5407
5408 mService.setDefaultAssistantForUser(0);
5409
5410 verify(mNotificationAssistantAccessGrantedCallback)
5411 .onGranted(eq(xmlConfig), eq(0), eq(true));
5412 }
5413
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005414 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04005415 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
5416 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
5417 generateResetComponentValues();
5418 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
5419 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5420 ComponentName deviceConfig1 = new ComponentName("device", "config1");
5421 ComponentName deviceConfig2 = new ComponentName("device", "config2");
5422 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
5423 changes.put(false, new ArrayList());
5424 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
5425 mService.getBinderService().clearData("device", 0, false);
5426 verify(mAssistants, times(1))
5427 .setPackageOrComponentEnabled(
5428 eq("device/config2"),
5429 eq(0), eq(true), eq(false));
5430 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5431 eq("device"), eq(0), eq(false), eq(true));
5432 }
5433
5434 @Test
5435 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
5436 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
5437 generateResetComponentValues();
5438 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
5439 ComponentName deviceConfig = new ComponentName("device", "config");
5440 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
5441 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
5442 changes.put(false, new ArrayList());
5443 when(mListeners.resetComponents(anyString(), anyInt()))
5444 .thenReturn(changes);
5445 mService.getBinderService().clearData("device", 0, false);
5446 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
5447 eq("device"), eq(0), eq(false), eq(true));
5448 }
5449
5450 @Test
5451 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
5452 ComponentName deviceConfig = new ComponentName("device", "config");
5453 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
5454 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
5455 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
5456 mService.getBinderService().clearData("device", 0, false);
5457 verify(mConditionProviders, times(1)).resetPackage(
5458 eq("device"), eq(0));
5459 }
5460
5461 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07005462 public void testFlagBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005463 setUpPrefsForBubbles(PKG, mUid,
5464 true /* global */,
5465 BUBBLE_PREFERENCE_ALL /* app */,
5466 true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07005467
Mady Mellor9e923e12019-12-17 16:08:46 -08005468 NotificationRecord nr =
5469 generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble");
Mady Mellor65dcaa92019-04-03 12:21:44 -07005470
Julia Reynolds24edc002020-01-29 16:35:32 -05005471 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5472 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005473 waitForIdle();
5474
5475 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5476 assertEquals(1, notifs.length);
5477 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
5478 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005479 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor65dcaa92019-04-03 12:21:44 -07005480 }
5481
5482 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07005483 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005484 setUpPrefsForBubbles(PKG, mUid,
5485 true /* global */,
5486 BUBBLE_PREFERENCE_NONE /* app */,
5487 true /* channel */);
Mady Mellorc6820342019-05-20 12:04:36 -07005488
Mady Mellor9e923e12019-12-17 16:08:46 -08005489 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5490 "testFlagBubble_noFlag_appNotAllowed");
Mady Mellorc6820342019-05-20 12:04:36 -07005491
Julia Reynolds24edc002020-01-29 16:35:32 -05005492 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5493 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorc6820342019-05-20 12:04:36 -07005494 waitForIdle();
5495
5496 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5497 assertEquals(1, notifs.length);
5498 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
5499 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005500 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorc6820342019-05-20 12:04:36 -07005501 }
5502
5503 @Test
Mady Mellor9e923e12019-12-17 16:08:46 -08005504 public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005505 setUpPrefsForBubbles(PKG, mUid,
5506 true /* global */,
5507 BUBBLE_PREFERENCE_ALL /* app */,
5508 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005509
Mady Mellorbe797962019-04-01 16:04:24 -07005510 // Notif with bubble metadata but not our other misc requirements
Mady Mellor9e923e12019-12-17 16:08:46 -08005511 Notification.Builder nb = new Notification.Builder(mContext,
5512 mTestNotificationChannel.getId())
5513 .setContentTitle("foo")
5514 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Mady Mellora92268c2020-03-09 17:25:08 -07005515 .setBubbleMetadata(getBubbleMetadata());
Mady Mellor9e923e12019-12-17 16:08:46 -08005516 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005517 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor9e923e12019-12-17 16:08:46 -08005518 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellorbe797962019-04-01 16:04:24 -07005519
5520 // Say we're foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05005521 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellorbe797962019-04-01 16:04:24 -07005522 IMPORTANCE_FOREGROUND);
Julia Reynolds24edc002020-01-29 16:35:32 -05005523 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5524 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005525 waitForIdle();
5526
Mady Mellor9e923e12019-12-17 16:08:46 -08005527 // if notif isn't configured properly it doesn't get to bubble just because app is
5528 // foreground.
Mady Mellorbe797962019-04-01 16:04:24 -07005529 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005530 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005531 }
5532
5533 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005534 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005535 setUpPrefsForBubbles(PKG, mUid,
5536 true /* global */,
5537 BUBBLE_PREFERENCE_ALL /* app */,
5538 true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005539
Mady Mellor9e923e12019-12-17 16:08:46 -08005540 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5541 "testFlagBubbleNotifs_flag_messaging");
Mady Mellorbe797962019-04-01 16:04:24 -07005542
Julia Reynolds24edc002020-01-29 16:35:32 -05005543 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5544 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07005545 waitForIdle();
5546
5547 // yes allowed, yes messaging, yes bubble
5548 assertTrue(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005549 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellorbe797962019-04-01 16:04:24 -07005550 }
5551
5552 @Test
Mady Mellor6ce11e72020-05-29 14:07:24 -07005553 public void testFlagBubbleNotifs_noFlag_noShortcut() throws RemoteException {
5554 setUpPrefsForBubbles(PKG, mUid,
5555 true /* global */,
5556 BUBBLE_PREFERENCE_ALL /* app */,
5557 true /* channel */);
5558
5559 Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false);
5560 nb.setShortcutId(null);
5561 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5562 null, mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005563 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor6ce11e72020-05-29 14:07:24 -07005564
5565 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
5566 sbn.getId(), sbn.getNotification(), sbn.getUserId());
5567 waitForIdle();
5568
5569 // no shortcut no bubble
5570 assertFalse(mService.getNotificationRecord(
5571 sbn.getKey()).getNotification().isBubbleNotification());
5572 }
5573
5574 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005575 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005576 setUpPrefsForBubbles(PKG, mUid,
5577 true /* global */,
5578 BUBBLE_PREFERENCE_NONE /* app */,
5579 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005580
Mady Mellor9e923e12019-12-17 16:08:46 -08005581 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5582 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed");
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005583
5584 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005585 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5586 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005587 waitForIdle();
5588
5589 // not allowed, no bubble
5590 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005591 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005592 }
5593
5594 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005595 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005596 setUpPrefsForBubbles(PKG, mUid,
5597 true /* global */,
5598 BUBBLE_PREFERENCE_ALL /* app */,
5599 true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005600
Mady Mellor9e923e12019-12-17 16:08:46 -08005601 // Messaging notif WITHOUT bubble metadata
5602 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
5603 null /* groupKey */, false /* isSummary */);
5604
5605 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5606 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
Julia Reynoldse61758a2020-06-10 10:26:44 -04005607 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor9e923e12019-12-17 16:08:46 -08005608 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005609
5610 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005611 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5612 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005613 waitForIdle();
5614
5615 // no bubble metadata, no bubble
5616 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005617 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005618 }
5619
5620 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005621 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07005622 setUpPrefsForBubbles(PKG, mUid,
5623 true /* global */,
5624 BUBBLE_PREFERENCE_ALL /* app */,
5625 false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005626
Mady Mellor9e923e12019-12-17 16:08:46 -08005627 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5628 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed");
Mady Mellora92268c2020-03-09 17:25:08 -07005629 nr.getChannel().lockFields(USER_LOCKED_ALLOW_BUBBLE);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005630
5631 // Post the notification
Julia Reynolds24edc002020-01-29 16:35:32 -05005632 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5633 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005634 waitForIdle();
5635
5636 // channel not allowed, no bubble
5637 assertFalse(mService.getNotificationRecord(
Julia Reynolds24edc002020-01-29 16:35:32 -05005638 nr.getSbn().getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005639 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005640
Mady Mellor49b1bf12019-03-29 12:00:02 -07005641 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005642 public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception {
Mady Mellor49b1bf12019-03-29 12:00:02 -07005643 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005644 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005645
5646 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005647 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5648 "testAppCancelNotifications_cancelsBubbles",
Julia Reynolds24edc002020-01-29 16:35:32 -05005649 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
5650 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005651 waitForIdle();
5652
5653 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5654 assertEquals(1, notifs.length);
5655 assertEquals(1, mService.getNotificationRecordCount());
5656
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005657 mBinderService.cancelNotificationWithTag(PKG, PKG,
Julia Reynolds24edc002020-01-29 16:35:32 -05005658 "testAppCancelNotifications_cancelsBubbles", nrBubble.getSbn().getId(),
5659 nrBubble.getSbn().getUserId());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005660 waitForIdle();
5661
5662 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5663 assertEquals(0, notifs2.length);
5664 assertEquals(0, mService.getNotificationRecordCount());
5665 }
5666
5667 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005668 public void testCancelAllNotificationsFromApp_cancelsBubble() throws Exception {
5669 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5670 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5671 mService.addNotification(nr);
5672
5673 mBinderService.cancelAllNotifications(PKG, nr.getSbn().getUserId());
5674 waitForIdle();
5675
5676 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5677 assertEquals(0, notifs.length);
5678 assertEquals(0, mService.getNotificationRecordCount());
5679 }
5680
5681 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005682 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5683 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5684 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005685 nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
Mady Mellor49b1bf12019-03-29 12:00:02 -07005686
5687 mService.addNotification(nrNormal);
5688 mService.addNotification(nrBubble);
5689
5690 mService.getBinderService().cancelNotificationsFromListener(null, null);
5691 waitForIdle();
5692
5693 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5694 assertEquals(1, notifs.length);
5695 assertEquals(1, mService.getNotificationRecordCount());
5696 }
5697
5698 @Test
Lyn Han675570a2020-06-05 23:31:22 -07005699 public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception {
5700 // Add non-bubble notif
5701 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5702 mService.addNotification(nr);
Mady Mellor49b1bf12019-03-29 12:00:02 -07005703
Lyn Han675570a2020-06-05 23:31:22 -07005704 // Cancel via listener
5705 String[] keys = {nr.getSbn().getKey()};
Mady Mellor49b1bf12019-03-29 12:00:02 -07005706 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5707 waitForIdle();
5708
Lyn Han675570a2020-06-05 23:31:22 -07005709 // Notif not active anymore
5710 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5711 assertEquals(0, notifs.length);
5712 assertEquals(0, mService.getNotificationRecordCount());
5713 // Cancel event is logged
5714 assertEquals(1, mNotificationRecordLogger.numCalls());
5715 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
5716 .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
5717 }
5718
5719 @Test
5720 public void testCancelNotificationsFromListener_suppressesBubble() throws Exception {
5721 // Add bubble notif
5722 setUpPrefsForBubbles(PKG, mUid,
5723 true /* global */,
5724 BUBBLE_PREFERENCE_ALL /* app */,
5725 true /* channel */);
5726 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
5727
5728 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5729 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5730 waitForIdle();
5731
5732 // Cancel via listener
5733 String[] keys = {nr.getSbn().getKey()};
5734 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5735 waitForIdle();
5736
5737 // Bubble notif active and suppressed
Mady Mellor49b1bf12019-03-29 12:00:02 -07005738 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5739 assertEquals(1, notifs.length);
5740 assertEquals(1, mService.getNotificationRecordCount());
Lyn Han675570a2020-06-05 23:31:22 -07005741 assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed());
Mady Mellor49b1bf12019-03-29 12:00:02 -07005742 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005743
Julia Reynolds4214da92019-04-10 15:04:06 -04005744 @Test
Beverly9e6a7642020-02-13 10:11:29 -05005745 public void testCancelAllNotificationsFromStatusBar_ignoresBubble() throws Exception {
5746 // GIVEN a notification bubble
5747 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5748 nr.getSbn().getNotification().flags |= FLAG_BUBBLE;
5749 mService.addNotification(nr);
5750
5751 // WHEN the status bar clears all notifications
5752 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
5753 nr.getSbn().getUserId());
5754 waitForIdle();
5755
5756 // THEN the bubble notification does not get removed
5757 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5758 assertEquals(1, notifs.length);
5759 assertEquals(1, mService.getNotificationRecordCount());
5760 }
5761
5762
5763 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005764 public void testGetAllowedAssistantAdjustments() throws Exception {
5765 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005766 assertNotNull(capabilities);
5767
5768 for (int i = capabilities.size() - 1; i >= 0; i--) {
5769 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005770 mBinderService.disallowAssistantAdjustment(capability);
5771 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5772 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005773 assertNotNull(currentCapabilities);
5774 assertFalse(currentCapabilities.contains(capability));
5775 }
5776 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005777
Julia Reynolds4214da92019-04-10 15:04:06 -04005778 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005779 public void testAdjustRestrictedKey() throws Exception {
5780 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005781 mService.addNotification(r);
5782 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005783
5784 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5785 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5786
5787 Bundle signals = new Bundle();
5788 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5789 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
Julia Reynolds24edc002020-01-29 16:35:32 -05005790 Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005791 "", r.getUser().getIdentifier());
5792
5793 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5794 r.applyAdjustments();
5795
5796 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5797 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5798 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005799
Julia Reynolds4214da92019-04-10 15:04:06 -04005800 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005801 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005802 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5803 .thenReturn(true);
5804 mService.setZenHelper(mock(ZenModeHelper.class));
5805 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005806 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5807 boolean isEnabled = true;
5808 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5809 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5810
5811 try {
5812 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005813 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005814 } catch (IllegalArgumentException e) {
5815 // yay
5816 }
5817
5818 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5819 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5820 mBinderService.addAutomaticZenRule(rule);
5821
5822 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5823 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5824 mBinderService.addAutomaticZenRule(rule);
5825 }
5826
Julia Reynolds4214da92019-04-10 15:04:06 -04005827 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005828 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5829 try {
5830 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5831 mUid + UserHandle.PER_USER_RANGE);
5832 fail("Cannot call cross user without permission");
5833 } catch (SecurityException e) {
5834 // pass
5835 }
5836
5837 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005838 enableInteractAcrossUsers();
Julia Reynolds657d1642019-03-27 12:15:57 -04005839 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5840 mUid + UserHandle.PER_USER_RANGE);
5841 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005842
Julia Reynolds4214da92019-04-10 15:04:06 -04005843 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005844 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5845 try {
Mady Mellora92268c2020-03-09 17:25:08 -07005846 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005847 mUid + UserHandle.PER_USER_RANGE);
5848 fail("Cannot call cross user without permission");
5849 } catch (SecurityException e) {
5850 // pass
5851 }
5852
5853 // cross user, with permission, no problem
Will Brockmancfd98302020-01-29 15:57:30 -05005854 enableInteractAcrossUsers();
Mady Mellora92268c2020-03-09 17:25:08 -07005855 mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005856 mUid + UserHandle.PER_USER_RANGE);
5857 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005858
Will Brockmancfd98302020-01-29 15:57:30 -05005859 private void enableInteractAcrossUsers() {
5860 TestablePermissions perms = mContext.getTestablePermissions();
5861 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5862 }
5863
Mady Mellora54e9fa2019-04-18 13:26:18 -07005864 @Test
5865 public void testNotificationBubbleChanged_false() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005866 setUpPrefsForBubbles(PKG, mUid,
5867 true /* global */,
5868 BUBBLE_PREFERENCE_ALL /* app */,
5869 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005870
Mady Mellor9e923e12019-12-17 16:08:46 -08005871 // Notif with bubble metadata
5872 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5873 "testNotificationBubbleChanged_false");
Mady Mellora54e9fa2019-04-18 13:26:18 -07005874
Julia Reynolds24edc002020-01-29 16:35:32 -05005875 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5876 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005877 waitForIdle();
5878
Mady Mellor66efd5e2019-05-15 13:38:11 -07005879 // Reset as this is called when the notif is first sent
5880 reset(mListeners);
5881
Mady Mellora54e9fa2019-04-18 13:26:18 -07005882 // First we were a bubble
5883 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5884 assertEquals(1, notifsBefore.length);
5885 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5886
5887 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005888 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005889 waitForIdle();
5890
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005891 // Make sure we are not a bubble
5892 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5893 assertEquals(1, notifsAfter.length);
5894 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005895 }
5896
5897 @Test
5898 public void testNotificationBubbleChanged_true() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005899 setUpPrefsForBubbles(PKG, mUid,
5900 true /* global */,
5901 BUBBLE_PREFERENCE_ALL /* app */,
5902 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005903
Mady Mellor9e923e12019-12-17 16:08:46 -08005904 // Notif that is not a bubble
Mady Mellora54e9fa2019-04-18 13:26:18 -07005905 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08005906 1, null, false);
Julia Reynolds24edc002020-01-29 16:35:32 -05005907 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5908 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005909 waitForIdle();
5910
5911 // Would be a normal notification because wouldn't have met requirements to bubble
5912 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5913 assertEquals(1, notifsBefore.length);
5914 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5915
Mady Mellor9e923e12019-12-17 16:08:46 -08005916 // Update the notification to be message style / meet bubble requirements
5917 NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel,
Julia Reynolds24edc002020-01-29 16:35:32 -05005918 nr.getSbn().getTag());
5919 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.getSbn().getTag(),
5920 nr2.getSbn().getId(), nr2.getSbn().getNotification(), nr2.getSbn().getUserId());
Mady Mellor9e923e12019-12-17 16:08:46 -08005921 waitForIdle();
Mady Mellora54e9fa2019-04-18 13:26:18 -07005922
Mady Mellor66efd5e2019-05-15 13:38:11 -07005923 // Reset as this is called when the notif is first sent
5924 reset(mListeners);
5925
Mady Mellora54e9fa2019-04-18 13:26:18 -07005926 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005927 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005928 waitForIdle();
5929
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005930 // Make sure we are a bubble
5931 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5932 assertEquals(1, notifsAfter.length);
5933 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005934 }
5935
5936 @Test
5937 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005938 setUpPrefsForBubbles(PKG, mUid,
5939 true /* global */,
5940 BUBBLE_PREFERENCE_ALL /* app */,
5941 true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005942
5943 // Notif that is not a bubble
Mady Mellor9e923e12019-12-17 16:08:46 -08005944 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds24edc002020-01-29 16:35:32 -05005945 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5946 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora54e9fa2019-04-18 13:26:18 -07005947 waitForIdle();
5948
Mady Mellor66efd5e2019-05-15 13:38:11 -07005949 // Reset as this is called when the notif is first sent
5950 reset(mListeners);
5951
Mady Mellora54e9fa2019-04-18 13:26:18 -07005952 // Would be a normal notification because wouldn't have met requirements to bubble
5953 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5954 assertEquals(1, notifsBefore.length);
5955 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5956
5957 // Notify we are now a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005958 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005959 waitForIdle();
5960
5961 // We still wouldn't be a bubble because the notification didn't meet requirements
5962 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5963 assertEquals(1, notifsAfter.length);
5964 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5965 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005966
5967 @Test
Mady Mellor13f9bc82020-03-24 19:09:28 -07005968 public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07005969 setUpPrefsForBubbles(PKG, mUid,
5970 true /* global */,
5971 BUBBLE_PREFERENCE_ALL /* app */,
5972 true /* channel */);
5973
Mady Mellor13f9bc82020-03-24 19:09:28 -07005974 // Notif with bubble metadata
5975 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
5976 "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
5977
5978 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5979 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5980 waitForIdle();
5981 // Flag shouldn't be modified
5982 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5983 assertFalse(recordToCheck.isFlagBubbleRemoved());
5984
5985 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07005986 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07005987 waitForIdle();
5988 // Flag should be modified
5989 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5990 assertTrue(recordToCheck.isFlagBubbleRemoved());
5991
5992
5993 // Update the notif
5994 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
5995 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
5996 waitForIdle();
5997 // And the flag is reset
5998 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
5999 assertFalse(recordToCheck.isFlagBubbleRemoved());
6000 }
6001
6002 @Test
6003 public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006004 setUpPrefsForBubbles(PKG, mUid,
6005 true /* global */,
6006 BUBBLE_PREFERENCE_ALL /* app */,
6007 true /* channel */);
6008
Mady Mellor13f9bc82020-03-24 19:09:28 -07006009 // Notif with bubble metadata
6010 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6011 "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
6012
6013 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6014 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6015 waitForIdle();
6016 // Flag shouldn't be modified
6017 NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
6018 assertFalse(recordToCheck.isFlagBubbleRemoved());
6019
6020 // Notify we're not a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07006021 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07006022 waitForIdle();
6023 // Flag should be modified
6024 recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
6025 assertTrue(recordToCheck.isFlagBubbleRemoved());
6026
6027 // Notify we are a bubble
Mady Mellor9adfe6a2020-03-30 17:23:26 -07006028 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true, 0);
Mady Mellor13f9bc82020-03-24 19:09:28 -07006029 waitForIdle();
6030 // And the flag is reset
6031 assertFalse(recordToCheck.isFlagBubbleRemoved());
6032 }
6033
6034 @Test
Mady Mellorf44b6832020-01-14 13:26:14 -08006035 public void testOnBubbleNotificationSuppressionChanged() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006036 setUpPrefsForBubbles(PKG, mUid,
6037 true /* global */,
6038 BUBBLE_PREFERENCE_ALL /* app */,
6039 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08006040
Mady Mellorf44b6832020-01-14 13:26:14 -08006041 // Bubble notification
6042 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
6043
Julia Reynolds24edc002020-01-29 16:35:32 -05006044 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6045 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellorf44b6832020-01-14 13:26:14 -08006046 waitForIdle();
6047
6048 // NOT suppressed
6049 Notification n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
6050 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
6051
6052 // Reset as this is called when the notif is first sent
6053 reset(mListeners);
6054
6055 // Test: update suppression to true
6056 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
6057 waitForIdle();
6058
6059 // Check
6060 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
6061 assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
6062
6063 // Reset to check again
6064 reset(mListeners);
6065
6066 // Test: update suppression to false
6067 mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
6068 waitForIdle();
6069
6070 // Check
6071 n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
6072 assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
6073 }
6074
6075 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04006076 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
6077 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6078 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05006079 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006080 waitForIdle();
6081
6082 // A notification exists for the given record
6083 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6084 assertEquals(1, notifsBefore.length);
6085
6086 reset(mPackageManager);
6087
6088 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6089
6090 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006091 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6092 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006093
6094 // Grant permission called for the UID of SystemUI under the target user ID
6095 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05006096 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
6097 anyInt(), eq(nr.getSbn().getUserId()));
Aran Inkfd2bfd32019-10-04 16:30:01 -04006098 }
6099
6100 @Test
Aran Ink979c9762019-10-24 16:09:45 -04006101 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
6102 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6103 waitForIdle();
6104
6105 // No notifications exist for the given record
6106 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6107 assertEquals(0, notifsBefore.length);
6108
6109 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6110 int uid = 0; // sysui on primary user
6111
6112 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006113 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6114 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006115
6116 // Grant permission still called if no NotificationRecord exists for the given key
6117 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05006118 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
6119 anyInt(), eq(nr.getSbn().getUserId()));
Aran Ink979c9762019-10-24 16:09:45 -04006120 }
6121
6122 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04006123 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
6124 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
6125 NotificationRecord nr =
6126 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
6127 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05006128 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006129 waitForIdle();
6130
6131 // A notification exists for the given record
6132 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
6133 assertEquals(1, notifsBefore.length);
6134
6135 reset(mPackageManager);
6136
6137 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6138
6139 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006140 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6141 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006142
6143 // Target user for the grant is USER_ALL instead of USER_SYSTEM
6144 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05006145 eq(nr.getSbn().getUid()), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(),
6146 anyInt(), eq(UserHandle.USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04006147 }
6148
6149 @Test
6150 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
6151 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
6152 int otherUserId = 11;
6153 NotificationRecord nr =
6154 generateNotificationRecord(mTestNotificationChannel, otherUserId);
6155 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
Julia Reynolds24edc002020-01-29 16:35:32 -05006156 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006157 waitForIdle();
6158
6159 // A notification exists for the given record
Julia Reynolds8613ca32022-02-11 17:08:58 -05006160 List<StatusBarNotification> notifsBefore =
6161 mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList();
6162 assertEquals(1, notifsBefore.size());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006163
6164 reset(mPackageManager);
6165
6166 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6167
6168 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04006169 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04006170 String sysuiPackage = "sysui";
6171 final String[] sysuiPackages = new String[] { sysuiPackage };
6172 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
6173
6174 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
6175 // time this is called
6176 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
6177 .thenReturn(otherUserUid);
6178
Aran Ink979c9762019-10-24 16:09:45 -04006179 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006180 nr.getKey(), uri, nr.getSbn().getUser(), nr.getSbn().getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04006181
6182 // Target user for the grant is USER_ALL instead of USER_SYSTEM
6183 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
Julia Reynolds24edc002020-01-29 16:35:32 -05006184 eq(otherUserUid), eq(nr.getSbn().getPackageName()), eq(uri), anyInt(), anyInt(),
Aran Inkfd2bfd32019-10-04 16:30:01 -04006185 eq(otherUserId));
6186 }
6187
6188 @Test
Aran Ink979c9762019-10-24 16:09:45 -04006189 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
6190 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6191 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04006192
Aran Ink979c9762019-10-24 16:09:45 -04006193 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6194 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04006195
Aran Ink979c9762019-10-24 16:09:45 -04006196 // create an inline record with two uris in it
6197 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006198 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6199 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006200 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006201 nr.getKey(), uri2, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6202 nr.getSbn().getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04006203
Aran Ink979c9762019-10-24 16:09:45 -04006204 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
6205 assertNotNull(record); // record exists
6206 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04006207
Julia Reynolds24edc002020-01-29 16:35:32 -05006208 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
6209 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006210
6211 // permissionOwner destroyed
6212 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
6213 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
6214 }
6215
6216
6217 @Test
6218 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
6219 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
6220 reset(mPackageManager);
6221
Julia Reynolds24edc002020-01-29 16:35:32 -05006222 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(),
6223 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006224
6225 // no permissionOwner destroyed
6226 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
6227 any(), eq(null), eq(~0), eq(nr.getUserId()));
6228 }
6229
6230 @Test
6231 public void testClearInlineReplyUriPermission_userAll() throws Exception {
6232 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
6233 UserHandle.USER_ALL);
6234 reset(mPackageManager);
6235
6236 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
6237 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
6238
6239 // create an inline record a uri in it
6240 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Julia Reynolds24edc002020-01-29 16:35:32 -05006241 nr.getKey(), uri1, nr.getSbn().getUser(), nr.getSbn().getPackageName(),
6242 nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006243
6244 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
6245 assertNotNull(record); // record exists
6246
Julia Reynolds24edc002020-01-29 16:35:32 -05006247 mService.mNotificationDelegate.clearInlineReplyUriPermissions(
6248 nr.getKey(), nr.getSbn().getUid());
Aran Ink979c9762019-10-24 16:09:45 -04006249
6250 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
6251 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
6252 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04006253 }
6254
6255 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006256 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006257 setUpPrefsForBubbles(PKG, mUid,
6258 true /* global */,
6259 BUBBLE_PREFERENCE_ALL /* app */,
6260 true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006261
Mady Mellor9e923e12019-12-17 16:08:46 -08006262 // And we are low ram
6263 when(mActivityManager.isLowRamDevice()).thenReturn(true);
6264
6265 // Notification that would typically bubble
6266 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6267 "testNotificationBubbles_disabled_lowRamDevice");
Julia Reynolds24edc002020-01-29 16:35:32 -05006268 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6269 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006270 waitForIdle();
6271
Mady Mellor9e923e12019-12-17 16:08:46 -08006272 // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled.
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006273 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6274 assertEquals(1, notifsAfter.length);
6275 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07006276 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04006277
6278 @Test
6279 public void testRemoveLargeRemoteViews() throws Exception {
6280 int removeSize = mContext.getResources().getInteger(
6281 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
6282
6283 RemoteViews rv = mock(RemoteViews.class);
6284 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
6285 when(rv.clone()).thenReturn(rv);
6286 RemoteViews rv1 = mock(RemoteViews.class);
6287 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
6288 when(rv1.clone()).thenReturn(rv1);
6289 RemoteViews rv2 = mock(RemoteViews.class);
6290 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
6291 when(rv2.clone()).thenReturn(rv2);
6292 RemoteViews rv3 = mock(RemoteViews.class);
6293 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
6294 when(rv3.clone()).thenReturn(rv3);
6295 RemoteViews rv4 = mock(RemoteViews.class);
6296 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
6297 when(rv4.clone()).thenReturn(rv4);
6298 // note: different!
6299 RemoteViews rv5 = mock(RemoteViews.class);
6300 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
6301 when(rv5.clone()).thenReturn(rv5);
6302
6303 Notification np = new Notification.Builder(mContext, "test")
6304 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6305 .setContentText("test")
6306 .setCustomContentView(rv)
6307 .setCustomBigContentView(rv1)
6308 .setCustomHeadsUpContentView(rv2)
6309 .build();
6310 Notification n = new Notification.Builder(mContext, "test")
6311 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6312 .setContentText("test")
6313 .setCustomContentView(rv3)
6314 .setCustomBigContentView(rv4)
6315 .setCustomHeadsUpContentView(rv5)
6316 .setPublicVersion(np)
6317 .build();
6318
6319 assertNotNull(np.contentView);
6320 assertNotNull(np.bigContentView);
6321 assertNotNull(np.headsUpContentView);
6322
6323 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
6324 assertNotNull(n.publicVersion.contentView);
6325 assertNotNull(n.publicVersion.bigContentView);
6326 assertNotNull(n.publicVersion.headsUpContentView);
6327
6328 mService.fixNotification(n, PKG, "tag", 9, 0);
6329
6330 assertNull(n.contentView);
6331 assertNull(n.bigContentView);
6332 assertNotNull(n.headsUpContentView);
6333 assertNull(n.publicVersion.contentView);
6334 assertNull(n.publicVersion.bigContentView);
6335 assertNull(n.publicVersion.headsUpContentView);
6336
6337 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
6338 }
Mady Mellor06b770c2019-08-29 18:01:00 -07006339
Colin Cross5ea7fb72019-12-18 17:16:36 -08006340 @Test
Mady Mellora7731962019-06-17 17:57:02 -07006341 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
6342 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006343 setUpPrefsForBubbles(PKG, mUid,
6344 true /* global */,
6345 BUBBLE_PREFERENCE_ALL /* app */,
6346 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006347
Mady Mellor9e923e12019-12-17 16:08:46 -08006348 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6349 "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground");
6350 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006351 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006352 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6353 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006354
6355 // Ensure we're not foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006356 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006357 IMPORTANCE_VISIBLE);
6358
Julia Reynolds24edc002020-01-29 16:35:32 -05006359 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6360 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006361 waitForIdle();
6362
6363 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006364 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006365 assertTrue(notif.isBubbleNotification());
6366
6367 // Our flags should have failed since we're not foreground
6368 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
6369 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
6370 }
6371
6372 @Test
6373 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
6374 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006375 setUpPrefsForBubbles(PKG, mUid,
6376 true /* global */,
6377 BUBBLE_PREFERENCE_ALL /* app */,
6378 true /* channel */);
Mady Mellora7731962019-06-17 17:57:02 -07006379
Mady Mellor9e923e12019-12-17 16:08:46 -08006380 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6381 "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground");
6382 // Modify metadata flags
Julia Reynolds24edc002020-01-29 16:35:32 -05006383 nr.getSbn().getNotification().getBubbleMetadata().setFlags(
Mady Mellor9e923e12019-12-17 16:08:46 -08006384 Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
6385 | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
Mady Mellora7731962019-06-17 17:57:02 -07006386
6387 // Ensure we are in the foreground
Julia Reynolds24edc002020-01-29 16:35:32 -05006388 when(mActivityManager.getPackageImportance(nr.getSbn().getPackageName())).thenReturn(
Mady Mellora7731962019-06-17 17:57:02 -07006389 IMPORTANCE_FOREGROUND);
6390
Julia Reynolds24edc002020-01-29 16:35:32 -05006391 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6392 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellora7731962019-06-17 17:57:02 -07006393 waitForIdle();
6394
6395 // yes allowed, yes messaging, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006396 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellora7731962019-06-17 17:57:02 -07006397 assertTrue(notif.isBubbleNotification());
6398
Mady Mellor9e923e12019-12-17 16:08:46 -08006399 // Our flags should have passed since we are foreground
Mady Mellora7731962019-06-17 17:57:02 -07006400 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
6401 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
6402 }
Mady Mellor22f2f072019-04-18 13:26:18 -07006403
6404 @Test
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006405 public void testNotificationBubbles_flagRemoved_whenShortcutRemoved()
6406 throws RemoteException {
Mady Mellora92268c2020-03-09 17:25:08 -07006407 setUpPrefsForBubbles(PKG, mUid,
6408 true /* global */,
6409 BUBBLE_PREFERENCE_ALL /* app */,
6410 true /* channel */);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006411
6412 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6413 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6414
6415 // Messaging notification with shortcut info
6416 Notification.BubbleMetadata metadata =
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006417 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006418 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6419 null /* groupKey */, false /* isSummary */);
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006420 nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006421 nb.setBubbleMetadata(metadata);
6422 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
Julia Reynoldse61758a2020-06-10 10:26:44 -04006423 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006424 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6425
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006426 // Test: Send the bubble notification
Julia Reynolds24edc002020-01-29 16:35:32 -05006427 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6428 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006429 waitForIdle();
6430
6431 // Verify:
6432
6433 // Make sure we register the callback for shortcut changes
6434 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6435
6436 // yes allowed, yes messaging w/shortcut, yes bubble
Julia Reynolds24edc002020-01-29 16:35:32 -05006437 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006438 assertTrue(notif.isBubbleNotification());
6439
Danning Chen28410f32020-04-21 10:28:52 -07006440 // Make sure the shortcut is cached.
6441 verify(mShortcutServiceInternal).cacheShortcuts(
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006442 anyInt(), any(), eq(PKG), eq(Collections.singletonList(VALID_CONVO_SHORTCUT_ID)),
Mehdi Alizadeha3d22ce2020-04-27 18:52:52 -07006443 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
Danning Chen28410f32020-04-21 10:28:52 -07006444
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006445 // Test: Remove the shortcut
Mady Mellor56515c42020-02-18 17:58:36 -08006446 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006447 launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04006448 UserHandle.getUserHandleForUid(mUid));
Mady Mellor56515c42020-02-18 17:58:36 -08006449 waitForIdle();
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006450
6451 // Verify:
6452
6453 // Make sure callback is unregistered
6454 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6455
6456 // We're no longer a bubble
Mady Mellordb0a6022020-05-13 11:34:50 -07006457 NotificationRecord notif2 = mService.getNotificationRecord(
6458 nr.getSbn().getKey());
6459 assertNull(notif2.getShortcutInfo());
6460 assertFalse(notif2.getNotification().isBubbleNotification());
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006461 }
6462
Mady Mellor56515c42020-02-18 17:58:36 -08006463 @Test
6464 public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
6465 throws RemoteException {
Danning Chen28410f32020-04-21 10:28:52 -07006466 final String shortcutId = "someshortcutId";
Mady Mellora92268c2020-03-09 17:25:08 -07006467 setUpPrefsForBubbles(PKG, mUid,
6468 true /* global */,
6469 BUBBLE_PREFERENCE_ALL /* app */,
6470 true /* channel */);
Mady Mellor56515c42020-02-18 17:58:36 -08006471
6472 ArgumentCaptor<LauncherApps.Callback> launcherAppsCallback =
6473 ArgumentCaptor.forClass(LauncherApps.Callback.class);
6474
6475 // Messaging notification with shortcut info
Mady Melloraa9ce172020-03-17 10:34:20 -07006476 Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
Danning Chen28410f32020-04-21 10:28:52 -07006477 shortcutId).build();
Mady Mellor56515c42020-02-18 17:58:36 -08006478 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6479 null /* groupKey */, false /* isSummary */);
Danning Chen28410f32020-04-21 10:28:52 -07006480 nb.setShortcutId(shortcutId);
Mady Mellor56515c42020-02-18 17:58:36 -08006481 nb.setBubbleMetadata(metadata);
6482 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
Julia Reynoldse61758a2020-06-10 10:26:44 -04006483 "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
Mady Mellor56515c42020-02-18 17:58:36 -08006484 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6485
6486 // Pretend the shortcut exists
6487 List<ShortcutInfo> shortcutInfos = new ArrayList<>();
6488 ShortcutInfo info = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006489 when(info.getPackage()).thenReturn(PKG);
Danning Chen28410f32020-04-21 10:28:52 -07006490 when(info.getId()).thenReturn(shortcutId);
Danning Chen07cfaa62020-04-20 15:16:41 -07006491 when(info.getUserId()).thenReturn(USER_SYSTEM);
Mady Mellor56515c42020-02-18 17:58:36 -08006492 when(info.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006493 when(info.isEnabled()).thenReturn(true);
Mady Mellor56515c42020-02-18 17:58:36 -08006494 shortcutInfos.add(info);
6495 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006496 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6497 anyString(), anyInt(), any())).thenReturn(true);
Mady Mellor56515c42020-02-18 17:58:36 -08006498
6499 // Test: Send the bubble notification
6500 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6501 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6502 waitForIdle();
6503
6504 // Verify:
6505
6506 // Make sure we register the callback for shortcut changes
6507 verify(mLauncherApps, times(1)).registerCallback(launcherAppsCallback.capture(), any());
6508
6509 // yes allowed, yes messaging w/shortcut, yes bubble
6510 Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
6511 assertTrue(notif.isBubbleNotification());
6512
Danning Chen28410f32020-04-21 10:28:52 -07006513 // Make sure the shortcut is cached.
6514 verify(mShortcutServiceInternal).cacheShortcuts(
6515 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
Mehdi Alizadeha3d22ce2020-04-27 18:52:52 -07006516 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
Danning Chen28410f32020-04-21 10:28:52 -07006517
Mady Mellor56515c42020-02-18 17:58:36 -08006518 // Test: Remove the notification
6519 mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6520 nr.getSbn().getId(), nr.getSbn().getUserId());
6521 waitForIdle();
6522
6523 // Verify:
6524
6525 // Make sure callback is unregistered
6526 verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
6527 }
6528
Mady Mellor2ac2d3a2020-01-08 17:18:54 -08006529 @Test
Mady Mellor22f2f072019-04-18 13:26:18 -07006530 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
6531 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006532 setUpPrefsForBubbles(PKG, mUid,
6533 true /* global */,
6534 BUBBLE_PREFERENCE_ALL /* app */,
6535 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006536
6537 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6538 true /* summaryAutoCancel */);
6539
6540 // Dismiss summary
6541 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6542 true);
Julia Reynolds24edc002020-01-29 16:35:32 -05006543 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
6544 nrSummary.getSbn().getTag(),
6545 nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
Mady Mellor22f2f072019-04-18 13:26:18 -07006546 NotificationStats.DISMISSAL_SHADE,
6547 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
6548 waitForIdle();
6549
6550 // The bubble should still exist
6551 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6552 assertEquals(1, notifsAfter.length);
6553 }
6554
6555 @Test
6556 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
6557 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006558 setUpPrefsForBubbles(PKG, mUid,
6559 true /* global */,
6560 BUBBLE_PREFERENCE_ALL /* app */,
6561 true /* channel */);
Mady Mellor22f2f072019-04-18 13:26:18 -07006562
6563 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
6564 true /* summaryAutoCancel */);
6565
6566 // Click summary
6567 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
6568 true);
6569 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6570 nrSummary.getKey(), nv);
6571 waitForIdle();
6572
6573 // The bubble should still exist
6574 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6575 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006576
6577 // Check we got the click log and associated dismissal logs
6578 assertEquals(6, mNotificationRecordLogger.numCalls());
6579 // Skip the notification-creation logs
6580 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6581 mNotificationRecordLogger.event(3));
6582 assertEquals(NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_CLICK,
6583 mNotificationRecordLogger.event(4));
6584 assertEquals(NotificationRecordLogger.NotificationCancelledEvent
6585 .NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED,
6586 mNotificationRecordLogger.event(5));
Mady Mellor22f2f072019-04-18 13:26:18 -07006587 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04006588
6589 @Test
Beverly9e6a7642020-02-13 10:11:29 -05006590 public void testNotificationBubbles_bubbleStays_whenClicked()
6591 throws Exception {
Mady Mellora92268c2020-03-09 17:25:08 -07006592 setUpPrefsForBubbles(PKG, mUid,
6593 true /* global */,
6594 BUBBLE_PREFERENCE_ALL /* app */,
6595 true /* channel */);
6596
Beverly9e6a7642020-02-13 10:11:29 -05006597 // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
Beverly9e6a7642020-02-13 10:11:29 -05006598 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
6599 nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
6600 mService.addNotification(nr);
6601
6602 // WHEN we click the notification
6603 final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
6604 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
6605 nr.getKey(), nv);
6606 waitForIdle();
6607
6608 // THEN the bubble should still exist
6609 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
6610 assertEquals(1, notifsAfter.length);
Will Brockman9918db92020-03-06 16:48:39 -05006611
6612 // Check we got the click log
6613 assertEquals(1, mNotificationRecordLogger.numCalls());
6614 assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
6615 mNotificationRecordLogger.event(0));
Beverly9e6a7642020-02-13 10:11:29 -05006616 }
6617
6618 @Test
Julia Reynolds57a974b2019-10-07 11:51:47 -04006619 public void testLoadDefaultApprovedServices_emptyResources() {
6620 TestableResources tr = mContext.getOrCreateTestableResources();
6621 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
6622 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
6623 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
6624 setDefaultAssistantInDeviceConfig("");
6625
6626 mService.loadDefaultApprovedServices(USER_SYSTEM);
6627
6628 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
6629 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
6630 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
6631 }
6632
6633 @Test
6634 public void testLoadDefaultApprovedServices_dnd() {
6635 TestableResources tr = mContext.getOrCreateTestableResources();
6636 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
6637 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
6638 .thenReturn(new ArraySet<>());
6639
6640 mService.loadDefaultApprovedServices(USER_SYSTEM);
6641
Jay Aliomer76e1f2722020-03-05 12:36:38 -05006642 verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
Julia Reynolds57a974b2019-10-07 11:51:47 -04006643 }
6644
6645 // TODO: add tests for the rest of the non-empty cases
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006646
6647 @Test
6648 public void testOnUnlockUser() {
6649 UserInfo ui = new UserInfo();
6650 ui.id = 10;
6651 mService.onUnlockUser(ui);
6652 waitForIdle();
6653
6654 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
6655 }
6656
6657 @Test
6658 public void testOnStopUser() {
6659 UserInfo ui = new UserInfo();
6660 ui.id = 10;
6661 mService.onStopUser(ui);
6662 waitForIdle();
6663
6664 verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
6665 }
6666
6667 @Test
6668 public void testOnBootPhase() {
6669 mService.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
6670
6671 verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
6672
6673 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
6674
6675 verify(mHistoryManager, times(1)).onBootPhaseAppsCanStart();
6676 }
6677
6678 @Test
6679 public void testHandleOnPackageChanged() {
6680 String[] pkgs = new String[] {PKG, PKG_N_MR1};
6681 int[] uids = new int[] {mUid, UserHandle.PER_USER_RANGE + 1};
6682
6683 mService.handleOnPackageChanged(false, USER_SYSTEM, pkgs, uids);
6684
6685 verify(mHistoryManager, never()).onPackageRemoved(anyInt(), anyString());
6686
6687 mService.handleOnPackageChanged(true, USER_SYSTEM, pkgs, uids);
6688
6689 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[0]), pkgs[0]);
6690 verify(mHistoryManager, times(1)).onPackageRemoved(UserHandle.getUserId(uids[1]), pkgs[1]);
6691 }
6692
6693 @Test
6694 public void testNotificationHistory_addNoisyNotification() throws Exception {
6695 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
Mady Mellor9e923e12019-12-17 16:08:46 -08006696 null /* tvExtender */);
Julia Reynolds24edc002020-01-29 16:35:32 -05006697 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6698 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
Julia Reynoldsb317ff72019-11-26 14:20:51 -05006699 waitForIdle();
6700
6701 verify(mHistoryManager, times(1)).addNotification(any());
6702 }
Julia Reynolds0f767342019-12-18 09:11:55 -05006703
6704 @Test
6705 public void createConversationNotificationChannel() throws Exception {
6706 NotificationChannel original = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
6707 original.setAllowBubbles(!original.canBubble());
6708 original.setShowBadge(!original.canShowBadge());
6709
6710 Parcel parcel = Parcel.obtain();
6711 original.writeToParcel(parcel, 0);
6712 parcel.setDataPosition(0);
6713 NotificationChannel orig = NotificationChannel.CREATOR.createFromParcel(parcel);
6714 assertEquals(original, orig);
6715 assertFalse(TextUtils.isEmpty(orig.getName()));
6716
6717 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6718 orig)));
6719
Julia Reynolds7c267522020-01-16 11:26:41 -05006720 mBinderService.createConversationNotificationChannelForPackage(
6721 PKG, mUid, "key", orig, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006722
6723 NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006724 PKG, 0, PKG, original.getId(), false, "friend");
Julia Reynolds0f767342019-12-18 09:11:55 -05006725
6726 assertEquals(original.getName(), friendChannel.getName());
6727 assertEquals(original.getId(), friendChannel.getParentChannelId());
6728 assertEquals("friend", friendChannel.getConversationId());
6729 assertEquals(null, original.getConversationId());
6730 assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
Mady Mellora92268c2020-03-09 17:25:08 -07006731 assertFalse(friendChannel.canBubble()); // can't be modified by app
Julia Reynolds0f767342019-12-18 09:11:55 -05006732 assertFalse(original.getId().equals(friendChannel.getId()));
6733 assertNotNull(friendChannel.getId());
6734 }
6735
6736 @Test
6737 public void deleteConversationNotificationChannels() throws Exception {
6738 NotificationChannel messagesParent =
6739 new NotificationChannel("messages", "messages", IMPORTANCE_HIGH);
6740 Parcel msgParcel = Parcel.obtain();
6741 messagesParent.writeToParcel(msgParcel, 0);
6742 msgParcel.setDataPosition(0);
6743
6744 NotificationChannel callsParent =
6745 new NotificationChannel("calls", "calls", IMPORTANCE_HIGH);
6746 Parcel callParcel = Parcel.obtain();
6747 callsParent.writeToParcel(callParcel, 0);
6748 callParcel.setDataPosition(0);
6749
6750 mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(
6751 messagesParent, callsParent)));
6752
6753 String conversationId = "friend";
6754
6755 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006756 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
6757 conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006758 mBinderService.createConversationNotificationChannelForPackage(
Julia Reynolds7c267522020-01-16 11:26:41 -05006759 PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
Julia Reynolds0f767342019-12-18 09:11:55 -05006760 conversationId);
6761
6762 NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006763 PKG, 0, PKG, messagesParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006764 NotificationChannel callsChild = mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006765 PKG, 0, PKG, callsParent.getId(), false, conversationId);
Julia Reynolds0f767342019-12-18 09:11:55 -05006766
6767 assertEquals(messagesParent.getId(), messagesChild.getParentChannelId());
6768 assertEquals(conversationId, messagesChild.getConversationId());
6769
6770 assertEquals(callsParent.getId(), callsChild.getParentChannelId());
6771 assertEquals(conversationId, callsChild.getConversationId());
6772
6773 mBinderService.deleteConversationNotificationChannels(PKG, mUid, conversationId);
6774
6775 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006776 PKG, 0, PKG, messagesParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006777 assertNull(mBinderService.getConversationNotificationChannel(
Julia Reynolds12ba4cf2020-01-10 16:01:38 -05006778 PKG, 0, PKG, callsParent.getId(), false, conversationId));
Julia Reynolds0f767342019-12-18 09:11:55 -05006779 }
Julia Reynolds24edc002020-01-29 16:35:32 -05006780
6781 @Test
6782 public void testCorrectCategory_systemOn_appCannotTurnOff() {
6783 int requested = 0;
6784 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6785
6786 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6787 system);
6788
6789 assertEquals(PRIORITY_CATEGORY_CONVERSATIONS, actual);
6790 }
6791
6792 @Test
6793 public void testCorrectCategory_systemOff_appTurnOff_noChanges() {
6794 int requested = PRIORITY_CATEGORY_CALLS;
6795 int system = PRIORITY_CATEGORY_CALLS;
6796
6797 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6798 system);
6799
6800 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6801 }
6802
6803 @Test
6804 public void testCorrectCategory_systemOn_appTurnOn_noChanges() {
6805 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6806 int system = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6807
6808 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6809 system);
6810
6811 assertEquals(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS, actual);
6812 }
6813
6814 @Test
6815 public void testCorrectCategory_systemOff_appCannotTurnOn() {
6816 int requested = PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS;
6817 int system = PRIORITY_CATEGORY_CALLS;
6818
6819 int actual = mService.correctCategory(requested, PRIORITY_CATEGORY_CONVERSATIONS,
6820 system);
6821
6822 assertEquals(PRIORITY_CATEGORY_CALLS, actual);
6823 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006824
6825 @Test
6826 public void testGetConversationsForPackage_hasShortcut() throws Exception {
6827 mService.setPreferencesHelper(mPreferencesHelper);
6828 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6829 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6830 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6831 channel1.setConversationId("parent1", "convo 1");
6832 convo1.setNotificationChannel(channel1);
6833 convos.add(convo1);
6834
6835 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6836 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6837 channel2.setConversationId("parent1", "convo 2");
6838 convo2.setNotificationChannel(channel2);
6839 convos.add(convo2);
6840 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6841
Julia Reynolds882f2062020-02-05 12:11:38 -05006842 ShortcutInfo si = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006843 when(si.getPackage()).thenReturn(PKG_P);
6844 when(si.getId()).thenReturn("convo");
6845 when(si.getUserId()).thenReturn(USER_SYSTEM);
Julia Reynolds8d34af82020-05-20 14:24:36 -04006846 when(si.getLabel()).thenReturn("Hello");
Mady Mellor774d5fe2020-03-05 11:35:03 -08006847 when(si.isLongLived()).thenReturn(true);
Julia Reynoldsfa273072020-04-14 15:31:21 -04006848 when(si.isEnabled()).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006849 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
Julia Reynoldsfa273072020-04-14 15:31:21 -04006850 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
6851 anyString(), anyInt(), any())).thenReturn(true);
Julia Reynolds882f2062020-02-05 12:11:38 -05006852
6853 List<ConversationChannelWrapper> conversations =
6854 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6855 assertEquals(si, conversations.get(0).getShortcutInfo());
6856 assertEquals(si, conversations.get(1).getShortcutInfo());
Mady Mellor774d5fe2020-03-05 11:35:03 -08006857 }
Julia Reynolds882f2062020-02-05 12:11:38 -05006858
Mady Mellor774d5fe2020-03-05 11:35:03 -08006859 @Test
6860 public void testGetConversationsForPackage_shortcut_notLongLived() throws Exception {
6861 mService.setPreferencesHelper(mPreferencesHelper);
6862 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6863 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6864 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6865 channel1.setConversationId("parent1", "convo 1");
6866 convo1.setNotificationChannel(channel1);
6867 convos.add(convo1);
6868
6869 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6870 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6871 channel2.setConversationId("parent1", "convo 2");
6872 convo2.setNotificationChannel(channel2);
6873 convos.add(convo2);
6874 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
6875
6876 ShortcutInfo si = mock(ShortcutInfo.class);
Danning Chen07cfaa62020-04-20 15:16:41 -07006877 when(si.getPackage()).thenReturn(PKG_P);
6878 when(si.getId()).thenReturn("convo");
6879 when(si.getUserId()).thenReturn(USER_SYSTEM);
Julia Reynolds8d34af82020-05-20 14:24:36 -04006880 when(si.getLabel()).thenReturn("Hello");
Mady Mellor774d5fe2020-03-05 11:35:03 -08006881 when(si.isLongLived()).thenReturn(false);
6882 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
6883
6884 List<ConversationChannelWrapper> conversations =
6885 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6886 assertNull(conversations.get(0).getShortcutInfo());
6887 assertNull(conversations.get(1).getShortcutInfo());
Julia Reynolds882f2062020-02-05 12:11:38 -05006888 }
6889
6890 @Test
6891 public void testGetConversationsForPackage_doesNotHaveShortcut() throws Exception {
6892 mService.setPreferencesHelper(mPreferencesHelper);
6893 ArrayList<ConversationChannelWrapper> convos = new ArrayList<>();
6894 ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
6895 NotificationChannel channel1 = new NotificationChannel("a", "a", 1);
6896 channel1.setConversationId("parent1", "convo 1");
6897 convo1.setNotificationChannel(channel1);
6898 convos.add(convo1);
6899
6900 ConversationChannelWrapper convo2 = new ConversationChannelWrapper();
6901 NotificationChannel channel2 = new NotificationChannel("b", "b", 1);
6902 channel2.setConversationId("parent1", "convo 2");
6903 convo2.setNotificationChannel(channel2);
6904 convos.add(convo2);
6905 when(mPreferencesHelper.getConversations(anyString(), anyInt())).thenReturn(convos);
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006906 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Julia Reynolds882f2062020-02-05 12:11:38 -05006907
6908 List<ConversationChannelWrapper> conversations =
6909 mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
6910 assertNull(conversations.get(0).getShortcutInfo());
6911 assertNull(conversations.get(1).getShortcutInfo());
6912 }
Mady Mellor57b34162020-04-01 08:44:00 -07006913
6914 @Test
6915 public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
6916 mService.setShortcutHelper(null);
6917 NotificationRecord nr =
6918 generateMessageBubbleNotifRecord(mTestNotificationChannel,
6919 "testShortcutHelperNull_doesntCrashEnqueue");
6920 try {
6921 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
6922 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6923 waitForIdle();
6924 } catch (Exception e) {
6925 fail(e.getMessage());
6926 }
6927 }
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006928
6929 @Test
Julia Reynolds8582df52020-04-24 18:30:59 -04006930 public void testRecordMessages_invalidMsg() throws RemoteException {
Julia Reynoldse61758a2020-06-10 10:26:44 -04006931 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6932 null /* groupKey */, false /* isSummary */);
6933 nb.setShortcutId(null);
6934 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
6935 "testRecordMessages_invalidMsg", mUid, 0, nb.build(),
6936 UserHandle.getUserHandleForUid(mUid), null, 0);
6937 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6938
Julia Reynoldsc76888d2020-05-04 15:36:09 -04006939 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
Julia Reynoldse61758a2020-06-10 10:26:44 -04006940 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006941 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6942 waitForIdle();
6943
Julia Reynoldse61758a2020-06-10 10:26:44 -04006944 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
6945 }
6946
6947 @Test
6948 public void testRecordMessages_invalidMsg_notMessageStyle() throws RemoteException {
6949 Notification.Builder nb = new Notification.Builder(mContext,
6950 mTestNotificationChannel.getId())
6951 .setContentTitle("foo")
6952 .setShortcutId(null)
6953 .setSmallIcon(android.R.drawable.sym_def_app_icon)
6954 .setCategory(Notification.CATEGORY_MESSAGE);
6955 StatusBarNotification sbn = new StatusBarNotification(PKG_O, PKG_O, 1,
6956 "testRecordMessages_invalidMsg_notMessageStyle", mUid, 0, nb.build(),
6957 UserHandle.getUserHandleForUid(mUid), null, 0);
6958 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6959
6960 when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
6961 mBinderService.enqueueNotificationWithTag(PKG_O, PKG_O, nr.getSbn().getTag(),
6962 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6963 waitForIdle();
6964
6965 // PKG_O is allowed to be in conversation space b/c of override in
6966 // TestableNotificationManagerService
6967 assertTrue(mBinderService.isInInvalidMsgState(PKG_O, mUid));
Julia Reynoldsa7dac432020-04-23 12:17:31 -04006968 }
Julia Reynolds8582df52020-04-24 18:30:59 -04006969
6970 @Test
6971 public void testRecordMessages_validMsg() throws RemoteException {
Julia Reynolds8582df52020-04-24 18:30:59 -04006972 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
6973 null /* groupKey */, false /* isSummary */);
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006974 nb.setShortcutId(null);
Julia Reynoldse61758a2020-06-10 10:26:44 -04006975 StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
6976 "testRecordMessages_validMsg", mUid, 0, nb.build(),
6977 UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynolds8582df52020-04-24 18:30:59 -04006978 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
6979
Julia Reynoldse61758a2020-06-10 10:26:44 -04006980 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
Julia Reynolds8582df52020-04-24 18:30:59 -04006981 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6982 waitForIdle();
6983
Julia Reynoldse61758a2020-06-10 10:26:44 -04006984 assertTrue(mBinderService.isInInvalidMsgState(PKG_P, mUid));
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006985
6986 nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6987 "testRecordMessages_validMsg");
6988
Julia Reynoldse61758a2020-06-10 10:26:44 -04006989 mBinderService.enqueueNotificationWithTag(PKG_P, PKG_P, nr.getSbn().getTag(),
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006990 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
6991 waitForIdle();
6992
Julia Reynoldse61758a2020-06-10 10:26:44 -04006993 assertFalse(mBinderService.isInInvalidMsgState(PKG_P, mUid));
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04006994 }
6995
6996 @Test
6997 public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException {
6998 NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
6999 "testRecordMessages_invalidMsg_afterValidMsg_1");
7000 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
7001 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
7002 waitForIdle();
7003 assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation());
7004
7005 mBinderService.cancelAllNotifications(PKG, mUid);
7006 waitForIdle();
7007
7008 Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
7009 null /* groupKey */, false /* isSummary */);
7010 nb.setShortcutId(null);
7011 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
7012 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
Julia Reynoldse61758a2020-06-10 10:26:44 -04007013 UserHandle.getUserHandleForUid(mUid), null, 0);
Julia Reynoldsbc23c7e2020-05-13 18:16:32 -04007014 nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
7015
7016 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
7017 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
7018 waitForIdle();
7019
7020 assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation());
Julia Reynolds8582df52020-04-24 18:30:59 -04007021 }
Julia Reynolds1a80b292020-05-01 11:55:57 -04007022
7023 @Test
7024 public void testCanPostFgsWhenOverLimit() throws RemoteException {
7025 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7026 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
7027 i, null, false).getSbn();
7028 mBinderService.enqueueNotificationWithTag(PKG, PKG,
7029 "testCanPostFgsWhenOverLimit",
7030 sbn.getId(), sbn.getNotification(), sbn.getUserId());
7031 }
7032
7033 final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
7034 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
7035 mBinderService.enqueueNotificationWithTag(PKG, PKG,
7036 "testCanPostFgsWhenOverLimit - fgs over limit!",
7037 sbn.getId(), sbn.getNotification(), sbn.getUserId());
7038
7039 waitForIdle();
7040
7041 StatusBarNotification[] notifs =
7042 mBinderService.getActiveNotifications(sbn.getPackageName());
7043 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
7044 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
7045 mService.getNotificationRecordCount());
7046 }
7047
7048 @Test
7049 public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
7050 for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
7051 StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
7052 i, null, false).getSbn();
7053 mBinderService.enqueueNotificationWithTag(PKG, PKG,
7054 "testCanPostFgsWhenOverLimit",
7055 sbn.getId(), sbn.getNotification(), sbn.getUserId());
7056 waitForIdle();
7057 }
7058
7059 final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
7060 100, null, false).getSbn();
7061 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
7062 mBinderService.enqueueNotificationWithTag(PKG, PKG,
7063 "testCanPostFgsWhenOverLimit - fgs over limit!",
7064 sbn.getId(), sbn.getNotification(), sbn.getUserId());
7065
7066 final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel,
7067 101, null, false).getSbn();
7068 mBinderService.enqueueNotificationWithTag(PKG, PKG,
7069 "testCanPostFgsWhenOverLimit - non fgs over limit!",
7070 sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
7071
7072 waitForIdle();
7073
7074 StatusBarNotification[] notifs =
7075 mBinderService.getActiveNotifications(sbn.getPackageName());
7076 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length);
7077 assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
7078 mService.getNotificationRecordCount());
7079 }
Julia Reynolds8613ca32022-02-11 17:08:58 -05007080
7081 @Test
7082 public void testGetActiveNotification_filtersUsers() throws Exception {
7083 when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
7084
7085 NotificationRecord nr0 =
7086 generateNotificationRecord(mTestNotificationChannel, 0);
7087 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
7088 nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId());
7089
7090 NotificationRecord nr10 =
7091 generateNotificationRecord(mTestNotificationChannel, 10);
7092 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
7093 nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId());
7094
7095 NotificationRecord nr11 =
7096 generateNotificationRecord(mTestNotificationChannel, 11);
7097 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
7098 nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId());
7099 waitForIdle();
7100
7101 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
7102 assertEquals(2, notifs.length);
7103 for (StatusBarNotification sbn : notifs) {
7104 if (sbn.getUserId() == 11) {
7105 fail("leaked data across users");
7106 }
7107 }
7108 }
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05007109}