blob: 4d0cfbc6ad11ded9e51d0486dd0784a46d5b3c01 [file] [log] [blame]
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.notification;
18
Beverly58b24532018-10-02 09:08:23 -040019import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
20import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
Mady Mellorbe797962019-04-01 16:04:24 -070021import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
22import static android.app.Notification.CATEGORY_CALL;
Mady Mellor22f2f072019-04-18 13:26:18 -070023import static android.app.Notification.FLAG_AUTO_CANCEL;
Mady Mellor49b1bf12019-03-29 12:00:02 -070024import static android.app.Notification.FLAG_BUBBLE;
Julia Reynoldse5c60452018-04-30 14:41:36 -040025import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050026import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
Julia Reynolds27c0a962018-12-10 12:37:28 -050027import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040028import static android.app.NotificationManager.IMPORTANCE_HIGH;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040029import static android.app.NotificationManager.IMPORTANCE_LOW;
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -050030import static android.app.NotificationManager.IMPORTANCE_MAX;
Julia Reynolds4da79702017-06-01 11:06:10 -040031import static android.app.NotificationManager.IMPORTANCE_NONE;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040032import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050033import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
34import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
35import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
36import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
37import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
38import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
39import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
40import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
41import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
Julia Reynoldse1816412017-10-24 10:39:11 -040042import static android.content.pm.PackageManager.FEATURE_WATCH;
Julia Reynolds4db59552017-06-30 13:34:01 -040043import static android.content.pm.PackageManager.PERMISSION_DENIED;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -040044import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -050045import static android.os.Build.VERSION_CODES.O_MR1;
46import static android.os.Build.VERSION_CODES.P;
Julia Reynolds57a974b2019-10-07 11:51:47 -040047import static android.os.UserHandle.USER_SYSTEM;
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -040048import static android.service.notification.Adjustment.KEY_IMPORTANCE;
49import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
Tony Makeda84a72018-11-19 17:01:32 +000050import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
51import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040052
Geoffrey Pitsch03533712017-01-05 10:30:07 -050053import static junit.framework.Assert.assertEquals;
Julia Reynolds727a7282017-04-13 10:54:01 -040054import static junit.framework.Assert.assertFalse;
Julia Reynolds92febc32017-10-26 11:30:31 -040055import static junit.framework.Assert.assertNotNull;
Julia Reynolds8617e4e2017-09-18 16:52:37 -040056import static junit.framework.Assert.assertNull;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050057import static junit.framework.Assert.assertTrue;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050058import static junit.framework.Assert.fail;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050059
Julia Reynolds5f20e9f2017-01-30 08:54:53 -050060import static org.mockito.Matchers.anyBoolean;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -040061import static org.mockito.Matchers.anyLong;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050062import static org.mockito.Matchers.anyString;
63import static org.mockito.Matchers.eq;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050064import static org.mockito.Mockito.any;
65import static org.mockito.Mockito.anyInt;
Julia Reynoldsb6c83742019-07-30 18:03:40 -040066import static org.mockito.Mockito.clearInvocations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -040067import static org.mockito.Mockito.doAnswer;
Julia Reynolds4afe2642019-05-01 08:42:24 -040068import static org.mockito.Mockito.doNothing;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050069import static org.mockito.Mockito.mock;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040070import static org.mockito.Mockito.never;
71import static org.mockito.Mockito.reset;
Julia Reynolds503ed942017-10-04 16:04:56 -040072import static org.mockito.Mockito.spy;
73import static org.mockito.Mockito.timeout;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050074import static org.mockito.Mockito.times;
75import static org.mockito.Mockito.verify;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050076import static org.mockito.Mockito.when;
77
Julia Reynolds68263d12017-06-21 14:21:19 -040078import android.app.ActivityManager;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -040079import android.app.AppOpsManager;
Julia Reynoldsa94365d2019-04-09 10:48:43 -040080import android.app.AutomaticZenRule;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040081import android.app.IActivityManager;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050082import android.app.INotificationManager;
Julia Reynolds268647a2018-10-25 16:54:27 -040083import android.app.ITransientNotification;
84import android.app.IUriGrantsManager;
Julia Reynoldsbaff4002016-12-15 11:34:26 -050085import android.app.Notification;
Julia Reynoldse0d711f2017-09-01 08:50:47 -040086import android.app.Notification.MessagingStyle.Message;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050087import android.app.NotificationChannel;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040088import android.app.NotificationChannelGroup;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050089import android.app.NotificationManager;
Mady Mellor7eb18ef2019-03-27 14:03:46 -070090import android.app.PendingIntent;
Mady Mellorbe797962019-04-01 16:04:24 -070091import android.app.Person;
Mady Mellora10448e2019-04-26 13:50:58 -070092import android.app.RemoteInput;
Jason Parks50322ff2018-03-27 10:23:33 -050093import android.app.admin.DevicePolicyManagerInternal;
Julia Reynolds7217dc92018-03-07 12:12:09 -050094import android.app.usage.UsageStatsManagerInternal;
Julia Reynolds73ed76b2017-04-04 17:04:38 -040095import android.companion.ICompanionDeviceManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -050096import android.content.ComponentName;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -060097import android.content.ContentUris;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -050098import android.content.Context;
Beverlyd4f96492017-08-02 13:36:11 -040099import android.content.Intent;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500100import android.content.pm.ApplicationInfo;
101import android.content.pm.IPackageManager;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500102import android.content.pm.PackageManager;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500103import android.content.pm.ParceledListSlice;
Julia Reynolds4afe2642019-05-01 08:42:24 -0400104import android.content.pm.UserInfo;
Kristian Monsen05f34792018-04-09 10:27:16 +0200105import android.content.res.Resources;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400106import android.graphics.Color;
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700107import android.graphics.drawable.Icon;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400108import android.media.AudioManager;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400109import android.net.Uri;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500110import android.os.Binder;
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400111import android.os.Build;
Julia Reynolds503ed942017-10-04 16:04:56 -0400112import android.os.Bundle;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400113import android.os.IBinder;
Julia Reynoldsf27d6b22017-04-13 15:48:16 -0400114import android.os.Process;
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400115import android.os.RemoteException;
Mady Mellorbe797962019-04-01 16:04:24 -0700116import android.os.SystemClock;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500117import android.os.UserHandle;
Julia Reynolds0c245002019-03-27 16:10:11 -0400118import android.os.UserManager;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000119import android.provider.DeviceConfig;
Jeff Sharkey6a97cc32018-04-17 12:16:20 -0600120import android.provider.MediaStore;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000121import android.provider.Settings;
Julia Reynolds503ed942017-10-04 16:04:56 -0400122import android.service.notification.Adjustment;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400123import android.service.notification.NotificationListenerService;
Julia Reynolds503ed942017-10-04 16:04:56 -0400124import android.service.notification.NotificationStats;
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500125import android.service.notification.StatusBarNotification;
Julia Reynoldsa94365d2019-04-09 10:48:43 -0400126import android.service.notification.ZenPolicy;
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400127import android.test.suitebuilder.annotation.SmallTest;
Jason Monk745d0a82017-04-17 11:34:22 -0400128import android.testing.AndroidTestingRunner;
Julia Reynolds92febc32017-10-26 11:30:31 -0400129import android.testing.TestableContext;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400130import android.testing.TestableLooper;
Jason Monk745d0a82017-04-17 11:34:22 -0400131import android.testing.TestableLooper.RunWithLooper;
Julia Reynolds7a6d07a2019-03-18 11:31:56 -0400132import android.testing.TestablePermissions;
Julia Reynolds57a974b2019-10-07 11:51:47 -0400133import android.testing.TestableResources;
Dan Sandler7d67bd42018-05-15 14:06:38 -0400134import android.text.Html;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400135import android.util.ArrayMap;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000136import android.util.ArraySet;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400137import android.util.AtomicFile;
Julia Reynolds469144c2019-06-21 14:30:28 -0400138import android.util.Xml;
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400139import android.widget.RemoteViews;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400140
Mady Mellor49b1bf12019-03-29 12:00:02 -0700141import androidx.annotation.Nullable;
142import androidx.test.InstrumentationRegistry;
143
Kristian Monsen05f34792018-04-09 10:27:16 +0200144import com.android.internal.R;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000145import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Julia Reynolds503ed942017-10-04 16:04:56 -0400146import com.android.internal.statusbar.NotificationVisibility;
Julia Reynolds469144c2019-06-21 14:30:28 -0400147import com.android.internal.util.FastXmlSerializer;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700148import com.android.server.LocalServices;
Beverly58b24532018-10-02 09:08:23 -0400149import com.android.server.SystemService;
Jason Monk74f5e362017-12-06 08:56:33 -0500150import com.android.server.UiServiceTestCase;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400151import com.android.server.lights.Light;
152import com.android.server.lights.LightsManager;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400153import com.android.server.notification.NotificationManagerService.NotificationAssistants;
154import com.android.server.notification.NotificationManagerService.NotificationListeners;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700155import com.android.server.uri.UriGrantsManagerInternal;
Beverly58b24532018-10-02 09:08:23 -0400156import com.android.server.wm.WindowManagerInternal;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400157
158import org.junit.After;
159import org.junit.Before;
160import org.junit.Test;
161import org.junit.runner.RunWith;
Julia Reynolds40f00d72017-12-12 10:47:32 -0500162import org.mockito.ArgumentCaptor;
163import org.mockito.Mock;
164import org.mockito.MockitoAnnotations;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400165import org.mockito.stubbing.Answer;
Julia Reynolds469144c2019-06-21 14:30:28 -0400166import org.xmlpull.v1.XmlPullParser;
167import org.xmlpull.v1.XmlSerializer;
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500168
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400169import java.io.BufferedInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400170import java.io.BufferedOutputStream;
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400171import java.io.ByteArrayInputStream;
Julia Reynolds469144c2019-06-21 14:30:28 -0400172import java.io.ByteArrayOutputStream;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400173import java.io.File;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400174import java.io.FileOutputStream;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400175import java.util.ArrayList;
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500176import java.util.Arrays;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000177import java.util.Collections;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400178import java.util.List;
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400179import java.util.Map;
Robin Leed107af62018-04-27 13:55:56 +0200180import java.util.function.Consumer;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500181
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400182
Geoffrey Pitsch8185d382017-05-19 18:41:32 -0400183@SmallTest
Jason Monk745d0a82017-04-17 11:34:22 -0400184@RunWith(AndroidTestingRunner.class)
185@RunWithLooper
Jason Monk74f5e362017-12-06 08:56:33 -0500186public class NotificationManagerServiceTest extends UiServiceTestCase {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500187 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
Tony Mak9a3c1f12019-03-04 16:04:42 +0000188
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400189 private final int mUid = Binder.getCallingUid();
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500190 private TestableNotificationManagerService mService;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500191 private INotificationManager mBinderService;
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400192 private NotificationManagerInternal mInternalService;
Julia Reynoldsda781472017-04-12 09:41:16 -0400193 @Mock
194 private IPackageManager mPackageManager;
195 @Mock
196 private PackageManager mPackageManagerClient;
Beverly58b24532018-10-02 09:08:23 -0400197 @Mock
198 private WindowManagerInternal mWindowManagerInternal;
Julia Reynolds92febc32017-10-26 11:30:31 -0400199 private TestableContext mContext = spy(getContext());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500200 private final String PKG = mContext.getPackageName();
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400201 private TestableLooper mTestableLooper;
Julia Reynoldsda781472017-04-12 09:41:16 -0400202 @Mock
203 private RankingHelper mRankingHelper;
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400204 @Mock private PreferencesHelper mPreferencesHelper;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400205 AtomicFile mPolicyFile;
206 File mFile;
207 @Mock
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400208 private NotificationUsageStats mUsageStats;
Julia Reynolds76c096d2017-06-19 08:16:04 -0400209 @Mock
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -0400210 private UsageStatsManagerInternal mAppUsageStats;
211 @Mock
Julia Reynolds76c096d2017-06-19 08:16:04 -0400212 private AudioManager mAudioManager;
Julia Reynolds68263d12017-06-21 14:21:19 -0400213 @Mock
214 ActivityManager mActivityManager;
Kristian Monsen05f34792018-04-09 10:27:16 +0200215 @Mock
216 Resources mResources;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400217 @Mock
218 RankingHandler mRankingHandler;
Julia Reynolds3ff26d22017-06-19 08:16:04 -0400219
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500220 private NotificationChannel mTestNotificationChannel = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -0500221 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Gustav Senntona8e38aa2019-01-22 14:55:39 +0000222
223 private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
224
Julia Reynoldsda781472017-04-12 09:41:16 -0400225 @Mock
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400226 private NotificationListeners mListeners;
227 @Mock private NotificationAssistants mAssistants;
Julia Reynoldsb852e562017-06-06 16:14:18 -0400228 @Mock private ConditionProviders mConditionProviders;
Julia Reynoldsda781472017-04-12 09:41:16 -0400229 private ManagedServices.ManagedServiceInfo mListener;
230 @Mock private ICompanionDeviceManager mCompanionMgr;
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400231 @Mock SnoozeHelper mSnoozeHelper;
Julia Reynolds8aebf352017-06-26 11:35:33 -0400232 @Mock GroupHelper mGroupHelper;
Julia Reynoldse0d711f2017-09-01 08:50:47 -0400233 @Mock
234 IBinder mPermOwner;
235 @Mock
236 IActivityManager mAm;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700237 @Mock
238 IUriGrantsManager mUgm;
239 @Mock
240 UriGrantsManagerInternal mUgmInternal;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -0400241 @Mock
242 AppOpsManager mAppOpsManager;
Annie Meng8b646fd2019-02-01 18:46:42 +0000243 @Mock
Tony Mak9a3c1f12019-03-04 16:04:42 +0000244 private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
245 mNotificationAssistantAccessGrantedCallback;
Julia Reynolds0c245002019-03-27 16:10:11 -0400246 @Mock
247 UserManager mUm;
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500248
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400249 // Use a Testable subclass so we can simulate calls from the system without failing.
250 private static class TestableNotificationManagerService extends NotificationManagerService {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500251 int countSystemChecks = 0;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700252 boolean isSystemUid = true;
Gustav Sennton44dc5882018-12-13 14:38:50 +0000253 int countLogSmartSuggestionsVisible = 0;
Tony Mak9a3c1f12019-03-04 16:04:42 +0000254 @Nullable
255 NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500256
Julia Reynolds0c245002019-03-27 16:10:11 -0400257 TestableNotificationManagerService(Context context) {
Amith Yamasani803eab692017-11-09 17:47:04 -0800258 super(context);
259 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400260
261 @Override
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400262 protected boolean isCallingUidSystem() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500263 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700264 return isSystemUid;
Geoffrey Pitsch27684152017-05-02 11:41:31 -0400265 }
266
267 @Override
268 protected boolean isCallerSystemOrPhone() {
Julia Reynoldsd78263d2018-01-30 10:40:41 -0500269 countSystemChecks++;
Brad Stenning8c991ea2018-07-31 13:33:01 -0700270 return isSystemUid;
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400271 }
Julia Reynolds727a7282017-04-13 10:54:01 -0400272
273 @Override
274 protected ICompanionDeviceManager getCompanionManager() {
275 return null;
276 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800277
278 @Override
Amith Yamasani7ec89412018-02-07 08:48:49 -0800279 protected void reportUserInteraction(NotificationRecord r) {
280 return;
281 }
Julia Reynoldsb62dad42018-11-26 16:33:02 -0500282
283 @Override
284 protected void handleSavePolicyFile() {
285 return;
286 }
Gustav Sennton44dc5882018-12-13 14:38:50 +0000287
288 @Override
Gustav Senntonc7d0d322019-01-07 15:36:41 +0000289 void logSmartSuggestionsVisible(NotificationRecord r, int notificationLocation) {
290 super.logSmartSuggestionsVisible(r, notificationLocation);
Gustav Sennton44dc5882018-12-13 14:38:50 +0000291 countLogSmartSuggestionsVisible++;
292 }
293
Annie Meng8b646fd2019-02-01 18:46:42 +0000294 @Override
Tony Mak9a3c1f12019-03-04 16:04:42 +0000295 protected void setNotificationAssistantAccessGrantedForUserInternal(
296 ComponentName assistant, int userId, boolean granted) {
297 if (mNotificationAssistantAccessGrantedCallback != null) {
298 mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
299 return;
300 }
301 super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
302 }
303
304 private void setNotificationAssistantAccessGrantedCallback(
305 @Nullable NotificationAssistantAccessGrantedCallback callback) {
306 this.mNotificationAssistantAccessGrantedCallback = callback;
307 }
308
309 interface NotificationAssistantAccessGrantedCallback {
310 void onGranted(ComponentName assistant, int userId, boolean granted);
311 }
312
Mady Mellorca0c24c2019-05-16 16:14:32 -0700313 @Override
314 protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
315 String packageName) {
316 // Tests for this not being true are in CTS NotificationManagerTest
317 return true;
318 }
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400319 }
320
Beverly58b24532018-10-02 09:08:23 -0400321 private class TestableToastCallback extends ITransientNotification.Stub {
322 @Override
323 public void show(IBinder windowToken) {
324 }
325
326 @Override
327 public void hide() {
328 }
329 }
330
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500331 @Before
332 public void setUp() throws Exception {
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000333 InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
334 "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
335
Julia Reynoldsda781472017-04-12 09:41:16 -0400336 MockitoAnnotations.initMocks(this);
Chris Wren89aa2262017-05-05 18:05:56 -0400337
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700338 LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
339 LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
Beverly58b24532018-10-02 09:08:23 -0400340 LocalServices.removeServiceForTest(WindowManagerInternal.class);
341 LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700342
Julia Reynolds4afe2642019-05-01 08:42:24 -0400343 doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
344
Julia Reynolds0c245002019-03-27 16:10:11 -0400345 mService = new TestableNotificationManagerService(mContext);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500346
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400347 // Use this testable looper.
348 mTestableLooper = TestableLooper.get(this);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500349 // MockPackageManager - default returns ApplicationInfo with matching calling UID
Julia Reynolds92febc32017-10-26 11:30:31 -0400350 mContext.setMockPackageManager(mPackageManagerClient);
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400351
Julia Reynolds73ed76b2017-04-04 17:04:38 -0400352 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400353 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
354 Object[] args = invocation.getArguments();
355 return getApplicationInfo((String) args[0], mUid);
356 });
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500357 when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400358 .thenAnswer((Answer<ApplicationInfo>) invocation -> {
359 Object[] args = invocation.getArguments();
360 return getApplicationInfo((String) args[0], mUid);
361 });
Julia Reynolds92febc32017-10-26 11:30:31 -0400362 when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500363 final LightsManager mockLightsManager = mock(LightsManager.class);
364 when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
Julia Reynolds76c096d2017-06-19 08:16:04 -0400365 when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
Julia Reynoldse1816412017-10-24 10:39:11 -0400366 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700367 when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
Julia Reynolds268647a2018-10-25 16:54:27 -0400368 when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
Julia Reynolds4214da92019-04-10 15:04:06 -0400369 when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400370 mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500371
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400372 // write to a test file; the system file isn't readable from tests
Julia Reynoldsb852e562017-06-06 16:14:18 -0400373 mFile = new File(mContext.getCacheDir(), "test.xml");
374 mFile.createNewFile();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400375 final String preupgradeXml = "<notification-policy></notification-policy>";
376 mPolicyFile = new AtomicFile(mFile);
377 FileOutputStream fos = mPolicyFile.startWrite();
378 fos.write(preupgradeXml.getBytes());
379 mPolicyFile.finishWrite(fos);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400380
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400381 // Setup managed services
382 mListener = mListeners.new ManagedServiceInfo(
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400383 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
Jay Aliomer4204f252019-08-26 11:36:53 -0400384 ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
385 ArraySet<ComponentName> components = new ArraySet<>();
386 components.add(defaultComponent);
387 when(mListeners.getDefaultComponents()).thenReturn(components);
388 when(mConditionProviders.getDefaultPackages())
389 .thenReturn(new ArraySet<>(Arrays.asList("config")));
390 when(mAssistants.getDefaultComponents()).thenReturn(components);
391 when(mAssistants.queryPackageForServices(
392 anyString(), anyInt(), anyInt())).thenReturn(components);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400393 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
394 ManagedServices.Config listenerConfig = new ManagedServices.Config();
395 listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
396 when(mListeners.getConfig()).thenReturn(listenerConfig);
397 ManagedServices.Config assistantConfig = new ManagedServices.Config();
398 assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS;
399 when(mAssistants.getConfig()).thenReturn(assistantConfig);
400 ManagedServices.Config dndConfig = new ManagedServices.Config();
401 dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS;
402 when(mConditionProviders.getConfig()).thenReturn(dndConfig);
403
Julia Reynolds418a8ff2019-03-21 10:45:10 -0400404 when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
405
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400406 mService.init(mTestableLooper.getLooper(), mRankingHandler,
Julia Reynolds4afe2642019-05-01 08:42:24 -0400407 mPackageManager, mPackageManagerClient, mockLightsManager,
408 mListeners, mAssistants, mConditionProviders,
409 mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
410 mGroupHelper, mAm, mAppUsageStats,
411 mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
412 mAppOpsManager, mUm);
413 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
414
Julia Reynolds503ed942017-10-04 16:04:56 -0400415 mService.setAudioManager(mAudioManager);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500416
417 // Tests call directly into the Binder.
Julia Reynolds503ed942017-10-04 16:04:56 -0400418 mBinderService = mService.getBinderService();
419 mInternalService = mService.getInternalService();
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500420
421 mBinderService.createNotificationChannels(
422 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400423 assertNotNull(mBinderService.getNotificationChannel(
424 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400425 clearInvocations(mRankingHandler);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500426 }
427
Julia Reynoldsb852e562017-06-06 16:14:18 -0400428 @After
429 public void tearDown() throws Exception {
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400430 if (mFile != null) mFile.delete();
Tony Mak9a3c1f12019-03-04 16:04:42 +0000431 clearDeviceConfig();
Stanislav Zholnin872afd42019-03-12 15:57:25 +0000432 InstrumentationRegistry.getInstrumentation()
433 .getUiAutomation().dropShellPermissionIdentity();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400434 }
435
Jay Aliomer4204f252019-08-26 11:36:53 -0400436 private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
437 ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
438 changed.put(true, new ArrayList<>());
439 changed.put(false, new ArrayList<>());
440 return changed;
441 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -0400442 private ApplicationInfo getApplicationInfo(String pkg, int uid) {
443 final ApplicationInfo applicationInfo = new ApplicationInfo();
444 applicationInfo.uid = uid;
445 switch (pkg) {
446 case PKG_N_MR1:
447 applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
448 break;
449 case PKG_O:
450 applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
451 break;
452 case PKG_P:
453 applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
454 break;
455 default:
456 applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
457 break;
458 }
459 return applicationInfo;
460 }
461
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500462 public void waitForIdle() {
Geoffrey Pitsch415e4542017-04-10 13:12:58 -0400463 mTestableLooper.processAllMessages();
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500464 }
465
Mady Mellorc6820342019-05-20 12:04:36 -0700466 private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
467 boolean channelEnabled) {
468 mService.setPreferencesHelper(mPreferencesHelper);
Lyn Han4463f842019-07-09 15:27:28 -0700469 when(mPreferencesHelper.bubblesEnabled()).thenReturn(globalEnabled);
Mady Mellorc6820342019-05-20 12:04:36 -0700470 when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
471 when(mPreferencesHelper.getNotificationChannel(
472 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
473 mTestNotificationChannel);
474 when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
475 mTestNotificationChannel.getImportance());
476 mTestNotificationChannel.setAllowBubbles(channelEnabled);
477 }
478
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500479 private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
480 Notification.Builder nb = new Notification.Builder(mContext, "a")
481 .setContentTitle("foo")
482 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400483 StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid,
484 "tag" + System.currentTimeMillis(), uid, 0,
Julia Reynolds7bcb57b2018-01-22 10:37:58 -0500485 nb.build(), new UserHandle(userId), null, postTime);
486 return sbn;
487 }
488
Mady Mellor22f2f072019-04-18 13:26:18 -0700489
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400490 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
491 String groupKey, boolean isSummary) {
Mady Mellor22f2f072019-04-18 13:26:18 -0700492 return generateNotificationRecord(channel, id, groupKey, isSummary, false /* isBubble */);
493 }
494
495 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
496 String groupKey, boolean isSummary, boolean isBubble) {
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400497 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
498 .setContentTitle("foo")
499 .setSmallIcon(android.R.drawable.sym_def_app_icon)
500 .setGroup(groupKey)
501 .setGroupSummary(isSummary);
Mady Mellor22f2f072019-04-18 13:26:18 -0700502 if (isBubble) {
503 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
504 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400505
506 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id,
507 "tag" + System.currentTimeMillis(), mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400508 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000509 return new NotificationRecord(mContext, sbn, channel);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -0400510 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400511
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500512 private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500513 return generateNotificationRecord(channel, null);
514 }
515
516 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
517 Notification.TvExtender extender) {
Mady Mellorbe797962019-04-01 16:04:24 -0700518 return generateNotificationRecord(channel, extender, false /* isBubble */);
519 }
520
521 private NotificationRecord generateNotificationRecord(NotificationChannel channel,
522 Notification.TvExtender extender, boolean isBubble) {
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500523 if (channel == null) {
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -0500524 channel = mTestNotificationChannel;
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500525 }
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500526 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500527 .setContentTitle("foo")
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500528 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -0500529 if (extender != null) {
530 nb.extend(extender);
531 }
Mady Mellorbe797962019-04-01 16:04:24 -0700532 if (isBubble) {
533 nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
534 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400535 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400536 nb.build(), new UserHandle(mUid), null, 0);
Geoffrey Pitscha22f6442017-05-05 16:47:38 +0000537 return new NotificationRecord(mContext, sbn, channel);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -0500538 }
539
Aran Inkfd2bfd32019-10-04 16:30:01 -0400540 private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
541 if (channel == null) {
542 channel = mTestNotificationChannel;
543 }
544 Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
545 .setContentTitle("foo")
546 .setSmallIcon(android.R.drawable.sym_def_app_icon);
547 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
548 nb.build(), new UserHandle(userId), null, 0);
549 return new NotificationRecord(mContext, sbn, channel);
550 }
551
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400552 private Map<String, Answer> getSignalExtractorSideEffects() {
553 Map<String, Answer> answers = new ArrayMap<>();
554
555 answers.put("override group key", invocationOnMock -> {
556 ((NotificationRecord) invocationOnMock.getArguments()[0])
557 .setOverrideGroupKey("bananas");
558 return null;
559 });
560 answers.put("override people", invocationOnMock -> {
561 ((NotificationRecord) invocationOnMock.getArguments()[0])
562 .setPeopleOverride(new ArrayList<>());
563 return null;
564 });
565 answers.put("snooze criteria", invocationOnMock -> {
566 ((NotificationRecord) invocationOnMock.getArguments()[0])
567 .setSnoozeCriteria(new ArrayList<>());
568 return null;
569 });
570 answers.put("notification channel", invocationOnMock -> {
571 ((NotificationRecord) invocationOnMock.getArguments()[0])
572 .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
573 return null;
574 });
575 answers.put("badging", invocationOnMock -> {
576 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
577 r.setShowBadge(!r.canShowBadge());
578 return null;
579 });
Julia Reynolds4509ce72019-01-31 13:12:43 -0500580 answers.put("bubbles", invocationOnMock -> {
581 NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
582 r.setAllowBubble(!r.canBubble());
583 return null;
584 });
Julia Reynoldseb3dca72017-07-11 10:39:58 -0400585 answers.put("package visibility", invocationOnMock -> {
586 ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
587 Notification.VISIBILITY_SECRET);
588 return null;
589 });
590
591 return answers;
592 }
593
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -0400594 private void clearDeviceConfig() {
595 DeviceConfig.resetToDefaults(
596 Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
597 }
598
599 private void setDefaultAssistantInDeviceConfig(String componentName) {
600 DeviceConfig.setProperty(
601 DeviceConfig.NAMESPACE_SYSTEMUI,
602 SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
603 componentName,
604 false);
605 }
606
Mady Mellor7eb18ef2019-03-27 14:03:46 -0700607 private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() {
608 PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
609 return new Notification.BubbleMetadata.Builder()
610 .setIntent(pi)
611 .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon));
612 }
613
Mady Mellor22f2f072019-04-18 13:26:18 -0700614 private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel)
615 throws RemoteException {
616
617 // Notification that has bubble metadata
618 NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel, 1,
619 "BUBBLE_GROUP", false /* isSummary */, true /* isBubble */);
620
621 // Make the package foreground so that we're allowed to be a bubble
622 when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn(
623 IMPORTANCE_FOREGROUND);
624
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400625 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700626 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
627 waitForIdle();
628
629 // Make sure we are a bubble
630 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
631 assertEquals(1, notifsAfter.length);
632 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
633
634 // Plain notification without bubble metadata
635 NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2,
636 "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400637 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700638 nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId());
639 waitForIdle();
640
641 notifsAfter = mBinderService.getActiveNotifications(PKG);
642 assertEquals(2, notifsAfter.length);
643
644 // Summary notification for both of those
645 NotificationRecord nrSummary = generateNotificationRecord(mTestNotificationChannel, 3,
646 "BUBBLE_GROUP", true /* isSummary */, false /* isBubble */);
647 if (summaryAutoCancel) {
648 nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
649 }
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400650 mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.sbn.getTag(),
Mady Mellor22f2f072019-04-18 13:26:18 -0700651 nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId());
652 waitForIdle();
653
654 notifsAfter = mBinderService.getActiveNotifications(PKG);
655 assertEquals(3, notifsAfter.length);
656
657 return nrSummary;
658 }
659
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500660 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500661 public void testCreateNotificationChannels_SingleChannel() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500662 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500663 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400664 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500665 new ParceledListSlice(Arrays.asList(channel)));
666 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400667 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500668 assertTrue(createdChannel != null);
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500669 }
670
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500671 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500672 public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500673 try {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400674 mBinderService.createNotificationChannels(PKG,
Kristian Monsen05f34792018-04-09 10:27:16 +0200675 new ParceledListSlice(Arrays.asList((Object[])null)));
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -0500676 fail("Exception should be thrown immediately.");
677 } catch (NullPointerException e) {
678 // pass
679 }
680 }
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500681
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500682 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500683 public void testCreateNotificationChannels_TwoChannels() throws Exception {
684 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500685 new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500686 final NotificationChannel channel2 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500687 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400688 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500689 new ParceledListSlice(Arrays.asList(channel1, channel2)));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400690 assertTrue(mBinderService.getNotificationChannel(
691 PKG, mContext.getUserId(), PKG, "id1") != null);
692 assertTrue(mBinderService.getNotificationChannel(
693 PKG, mContext.getUserId(), PKG, "id2") != null);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500694 }
695
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500696 @Test
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400697 public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
698 throws Exception {
699 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500700 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400701 mBinderService.createNotificationChannels(PKG,
702 new ParceledListSlice(Arrays.asList(channel)));
703
704 // Recreating the channel doesn't throw, but ignores importance.
705 final NotificationChannel dupeChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400706 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400707 mBinderService.createNotificationChannels(PKG,
708 new ParceledListSlice(Arrays.asList(dupeChannel)));
709 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400710 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500711 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400712 }
713
714 @Test
715 public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
716 throws Exception {
717 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500718 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400719 mBinderService.createNotificationChannels(PKG,
720 new ParceledListSlice(Arrays.asList(channel)));
721
722 // Recreating with a lower importance is allowed to modify the channel.
723 final NotificationChannel dupeChannel =
724 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
725 mBinderService.createNotificationChannels(PKG,
726 new ParceledListSlice(Arrays.asList(dupeChannel)));
727 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400728 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Geoffrey Pitsch76a3aa02017-07-26 15:07:34 -0400729 assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
730 }
731
732 @Test
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400733 public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
734 throws Exception {
735 final NotificationChannel channel =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500736 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400737 mBinderService.createNotificationChannels(PKG,
738 new ParceledListSlice(Arrays.asList(channel)));
739
740 // The user modifies importance directly, can no longer be changed by the app.
741 final NotificationChannel updatedChannel =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400742 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400743 mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
744
745 // Recreating with a lower importance leaves channel unchanged.
746 final NotificationChannel dupeChannel =
747 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
748 mBinderService.createNotificationChannels(PKG,
749 new ParceledListSlice(Arrays.asList(dupeChannel)));
750 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400751 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400752 assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400753 }
754
755 @Test
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500756 public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
757 throws Exception {
758 final NotificationChannel channel1 =
Julia Reynolds27c0a962018-12-10 12:37:28 -0500759 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500760 final NotificationChannel channel2 =
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400761 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400762 mBinderService.createNotificationChannels(PKG,
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500763 new ParceledListSlice(Arrays.asList(channel1, channel2)));
764 final NotificationChannel createdChannel =
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400765 mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
Julia Reynolds27c0a962018-12-10 12:37:28 -0500766 assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
Geoffrey Pitsch03533712017-01-05 10:30:07 -0500767 }
768
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500769 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500770 public void testBlockedNotifications_suspended() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500771 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
772
773 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400774 IMPORTANCE_HIGH);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500775 NotificationRecord r = generateNotificationRecord(channel);
Beverly3c707b42018-09-14 09:49:07 -0400776
777 // isBlocked is only used for user blocking, not app suspension
778 assertFalse(mService.isBlocked(r, mUsageStats));
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500779 }
780
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500781 @Test
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500782 public void testBlockedNotifications_blockedChannel() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500783 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
784
785 NotificationChannel channel = new NotificationChannel("id", "name",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400786 NotificationManager.IMPORTANCE_NONE);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500787 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400788 assertTrue(mService.isBlocked(r, mUsageStats));
Geoffrey Pitschd5bcf212017-06-01 15:45:35 -0400789 verify(mUsageStats, times(1)).registerBlocked(eq(r));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400790
791 mBinderService.createNotificationChannels(
792 PKG, new ParceledListSlice(Arrays.asList(channel)));
793 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400794 mBinderService.enqueueNotificationWithTag(PKG, PKG,
795 "testBlockedNotifications_blockedChannel",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400796 sbn.getId(), sbn.getNotification(), sbn.getUserId());
797 waitForIdle();
798 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
799 }
800
801 @Test
802 public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
803 throws Exception {
804 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
805
806 NotificationChannel channel = new NotificationChannel("blocked", "name",
807 NotificationManager.IMPORTANCE_NONE);
808 mBinderService.createNotificationChannels(
809 PKG, new ParceledListSlice(Arrays.asList(channel)));
810
811 final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400812 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400813 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400814 sbn.getId(), sbn.getNotification(), sbn.getUserId());
815 waitForIdle();
816 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
817 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -0400818 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400819 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
820 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400821 }
822
823 @Test
824 public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
825 throws Exception {
826 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
827
828 NotificationChannel channel =
829 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
830 mBinderService.createNotificationChannels(
831 PKG, new ParceledListSlice(Arrays.asList(channel)));
832
833 NotificationChannel update =
834 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
835 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
836 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400837 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
838 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400839
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700840 StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400841 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400842 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400843 sbn.getId(), sbn.getNotification(), sbn.getUserId());
844 waitForIdle();
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700845 // The first time a foreground service notification is shown, we allow the channel
846 // to be updated to allow it to be seen.
847 assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
848 assertEquals(IMPORTANCE_LOW,
849 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400850 assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
851 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldse4a47dd2019-06-07 13:40:59 -0400852 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700853 waitForIdle();
854
855 update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
856 update.setFgServiceShown(true);
857 mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
858 waitForIdle();
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400859 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
860 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700861
862 sbn = generateNotificationRecord(channel).sbn;
863 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400864 mBinderService.enqueueNotificationWithTag(PKG, PKG,
865 "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService",
Dianne Hackborn025d4a52018-04-30 16:23:26 -0700866 sbn.getId(), sbn.getNotification(), sbn.getUserId());
867 waitForIdle();
868 // The second time it is shown, we keep the user's preference.
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400869 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400870 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -0400871 assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
872 PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500873 }
874
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500875 @Test
Julia Reynolds005c8b92017-08-24 10:35:53 -0400876 public void testBlockedNotifications_blockedChannelGroup() throws Exception {
877 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -0400878 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400879 when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).
880 thenReturn(true);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400881
882 NotificationChannel channel = new NotificationChannel("id", "name",
883 NotificationManager.IMPORTANCE_HIGH);
884 channel.setGroup("something");
885 NotificationRecord r = generateNotificationRecord(channel);
Julia Reynolds503ed942017-10-04 16:04:56 -0400886 assertTrue(mService.isBlocked(r, mUsageStats));
Julia Reynolds005c8b92017-08-24 10:35:53 -0400887 verify(mUsageStats, times(1)).registerBlocked(eq(r));
888 }
889
890 @Test
Julia Reynolds4da79702017-06-01 11:06:10 -0400891 public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500892 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
893
Geoffrey Pitsch07532c32017-07-18 11:44:06 -0400894 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
Julia Reynolds4da79702017-06-01 11:06:10 -0400895
896 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400897 mBinderService.enqueueNotificationWithTag(PKG, PKG,
898 "testEnqueuedBlockedNotifications_blockedApp",
Julia Reynolds4da79702017-06-01 11:06:10 -0400899 sbn.getId(), sbn.getNotification(), sbn.getUserId());
900 waitForIdle();
901 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynoldsbaff4002016-12-15 11:34:26 -0500902 }
903
Geoffrey Pitsch16594462017-01-26 14:42:30 -0500904 @Test
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400905 public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
906 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
907
908 mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
909
910 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -0400911 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400912 mBinderService.enqueueNotificationWithTag(PKG, PKG,
913 "testEnqueuedBlockedNotifications_blockedAppForegroundService",
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400914 sbn.getId(), sbn.getNotification(), sbn.getUserId());
915 waitForIdle();
916 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -0400917 assertNull(mService.getNotificationRecord(sbn.getKey()));
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400918 }
919
Brad Stenning8c991ea2018-07-31 13:33:01 -0700920 /**
921 * Confirm the system user on automotive devices can use car categories
922 */
923 @Test
924 public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
925 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
926 .thenReturn(true);
927 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
928 Notification.CATEGORY_CAR_WARNING,
929 Notification.CATEGORY_CAR_INFORMATION);
930 int id = 0;
931 for (String category: categories) {
932 final StatusBarNotification sbn =
933 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
934 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400935 mBinderService.enqueueNotificationWithTag(PKG, PKG,
936 "testEnqueuedRestrictedNotifications_asSystem",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700937 sbn.getId(), sbn.getNotification(), sbn.getUserId());
938 }
939 waitForIdle();
940 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
941 }
942
943
944 /**
945 * Confirm restricted notification categories only apply to automotive.
946 */
947 @Test
948 public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
949 mService.isSystemUid = false;
950 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
951 .thenReturn(false);
952 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
953 Notification.CATEGORY_CAR_WARNING,
954 Notification.CATEGORY_CAR_INFORMATION);
955 int id = 0;
956 for (String category: categories) {
957 final StatusBarNotification sbn =
958 generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
959 sbn.getNotification().category = category;
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400960 mBinderService.enqueueNotificationWithTag(PKG, PKG,
961 "testEnqueuedRestrictedNotifications_notAutomotive",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700962 sbn.getId(), sbn.getNotification(), sbn.getUserId());
963 }
964 waitForIdle();
965 assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
966 }
967
968 /**
969 * Confirm if a non-system user tries to use the car categories on a automotive device that
970 * they will get a security exception
971 */
972 @Test
973 public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
974 mService.isSystemUid = false;
975 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
976 .thenReturn(true);
977 List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
978 Notification.CATEGORY_CAR_WARNING,
979 Notification.CATEGORY_CAR_INFORMATION);
980 for (String category: categories) {
981 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
982 sbn.getNotification().category = category;
983 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -0400984 mBinderService.enqueueNotificationWithTag(PKG, PKG,
985 "testEnqueuedRestrictedNotifications_badUser",
Brad Stenning8c991ea2018-07-31 13:33:01 -0700986 sbn.getId(), sbn.getNotification(), sbn.getUserId());
987 fail("Calls from non system apps should not allow use of restricted categories");
988 } catch (SecurityException e) {
989 // pass
990 }
991 }
992 waitForIdle();
993 assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
994 }
995
Julia Reynolds8617e4e2017-09-18 16:52:37 -0400996 @Test
Julia Reynoldsefcdff42018-08-09 09:42:56 -0400997 public void testBlockedNotifications_blockedByAssistant() throws Exception {
998 when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
Julia Reynolds27c0a962018-12-10 12:37:28 -0500999 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001000
1001 NotificationChannel channel = new NotificationChannel("id", "name",
1002 NotificationManager.IMPORTANCE_HIGH);
1003 NotificationRecord r = generateNotificationRecord(channel);
1004 mService.addEnqueuedNotification(r);
1005
Julia Reynolds27c0a962018-12-10 12:37:28 -05001006 Bundle bundle = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04001007 bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynolds27c0a962018-12-10 12:37:28 -05001008 Adjustment adjustment = new Adjustment(
1009 r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
1010 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04001011
1012 NotificationManagerService.PostNotificationRunnable runnable =
1013 mService.new PostNotificationRunnable(r.getKey());
1014 runnable.run();
1015 waitForIdle();
1016
1017 verify(mUsageStats, never()).registerPostedByApp(any());
1018 }
1019
1020 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001021 public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001022 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1023 "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001024 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001025 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001026 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001027 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001028 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001029 }
1030
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001031 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001032 public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001033 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1034 "testCancelNotificationImmediatelyAfterEnqueue", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001035 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001036 mBinderService.cancelNotificationWithTag(PKG, PKG,
1037 "testCancelNotificationImmediatelyAfterEnqueue", 0, 0);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001038 waitForIdle();
1039 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001040 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001041 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001042 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001043 }
1044
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001045 @Test
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001046 public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001047 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1048 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001049 generateNotificationRecord(null).getNotification(), 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001050 waitForIdle();
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001051 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1052 "testCancelNotificationWhilePostedAndEnqueued", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001053 generateNotificationRecord(null).getNotification(), 0);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001054 mBinderService.cancelNotificationWithTag(PKG, PKG,
1055 "testCancelNotificationWhilePostedAndEnqueued", 0, 0);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001056 waitForIdle();
1057 StatusBarNotification[] notifs =
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001058 mBinderService.getActiveNotifications(PKG);
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001059 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001060 assertEquals(0, mService.getNotificationRecordCount());
1061 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1062 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1063 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Geoffrey Pitschccc0b972017-02-15 10:52:26 -05001064 }
1065
1066 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001067 public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001068 NotificationRecord r = generateNotificationRecord(null);
1069 final StatusBarNotification sbn = r.sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001070 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1071 "testCancelNotificationsFromListenerImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001072 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001073 mBinderService.cancelNotificationsFromListener(null, null);
1074 waitForIdle();
1075 StatusBarNotification[] notifs =
1076 mBinderService.getActiveNotifications(sbn.getPackageName());
1077 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001078 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001079 }
1080
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001081 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001082 public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
1083 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001084 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1085 "testCancelAllNotificationsImmediatelyAfterEnqueue",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001086 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001087 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001088 waitForIdle();
1089 StatusBarNotification[] notifs =
1090 mBinderService.getActiveNotifications(sbn.getPackageName());
1091 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001092 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds080361e2017-07-13 11:23:12 -04001093 }
1094
1095 @Test
Evan Laird3ceaa9b2019-08-05 17:11:54 -04001096 public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
1097 throws Exception {
1098 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1099 sbn.getNotification().flags =
1100 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
1101 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
1102 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1103 mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
1104 waitForIdle();
1105 verify(mListeners, times(1)).notifyPostedLocked(any(), any());
1106 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
1107 }
1108
1109 @Test
Julia Reynolds080361e2017-07-13 11:23:12 -04001110 public void testUserInitiatedClearAll_noLeak() throws Exception {
1111 final NotificationRecord n = generateNotificationRecord(
1112 mTestNotificationChannel, 1, "group", true);
1113
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001114 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1115 "testUserInitiatedClearAll_noLeak",
Julia Reynolds080361e2017-07-13 11:23:12 -04001116 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
1117 waitForIdle();
1118
Julia Reynolds503ed942017-10-04 16:04:56 -04001119 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Julia Reynolds080361e2017-07-13 11:23:12 -04001120 n.getUserId());
1121 waitForIdle();
1122 StatusBarNotification[] notifs =
1123 mBinderService.getActiveNotifications(n.sbn.getPackageName());
1124 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001125 assertEquals(0, mService.getNotificationRecordCount());
1126 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
1127 verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
1128 assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
Julia Reynolds080361e2017-07-13 11:23:12 -04001129 }
1130
1131 @Test
1132 public void testCancelAllNotificationsCancelsChildren() throws Exception {
1133 final NotificationRecord parent = generateNotificationRecord(
1134 mTestNotificationChannel, 1, "group1", true);
1135 final NotificationRecord child = generateNotificationRecord(
1136 mTestNotificationChannel, 2, "group1", false);
1137
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001138 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1139 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds080361e2017-07-13 11:23:12 -04001140 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001141 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1142 "testCancelAllNotificationsCancelsChildren",
Julia Reynolds080361e2017-07-13 11:23:12 -04001143 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1144 waitForIdle();
1145
1146 mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
1147 waitForIdle();
Julia Reynolds503ed942017-10-04 16:04:56 -04001148 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001149 }
1150
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001151 @Test
Julia Reynolds0839c022017-06-15 15:24:01 -04001152 public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
1153 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1154 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001155 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1156 "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001157 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1158 }
1159 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1160 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001161
Julia Reynolds503ed942017-10-04 16:04:56 -04001162 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001163 }
1164
1165 @Test
1166 public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
1167 final NotificationRecord parent = generateNotificationRecord(
1168 mTestNotificationChannel, 1, "group1", true);
1169 final NotificationRecord parentAsChild = generateNotificationRecord(
1170 mTestNotificationChannel, 1, "group1", false);
1171 final NotificationRecord child = generateNotificationRecord(
1172 mTestNotificationChannel, 2, "group1", false);
1173
1174 // fully post parent notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001175 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1176 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001177 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
1178 waitForIdle();
1179
1180 // enqueue the child several times
1181 for (int i = 0; i < 10; i++) {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001182 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1183 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001184 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
1185 }
1186 // make the parent a child, which will cancel the child notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001187 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1188 "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash",
Julia Reynolds0839c022017-06-15 15:24:01 -04001189 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
1190 parentAsChild.sbn.getUserId());
1191 waitForIdle();
Julia Reynolds080361e2017-07-13 11:23:12 -04001192
Julia Reynolds503ed942017-10-04 16:04:56 -04001193 assertEquals(0, mService.getNotificationRecordCount());
Julia Reynolds0839c022017-06-15 15:24:01 -04001194 }
1195
1196 @Test
Jay Aliomerefe1c922019-09-19 16:42:16 -04001197 public void testAutobundledSummary_notificationAdded() {
1198 NotificationRecord summary =
1199 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1200 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1201 mService.addNotification(summary);
1202 mService.mSummaryByGroupKey.put("pkg", summary);
1203 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1204 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
Mady Mellor6d775f82019-11-12 16:12:19 -08001205 mService.updateAutobundledSummaryFlags(0, "pkg", true, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001206
1207 assertTrue(summary.sbn.isOngoing());
1208 }
1209
1210 @Test
1211 public void testAutobundledSummary_notificationRemoved() {
1212 NotificationRecord summary =
1213 generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
1214 summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
1215 summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1216 mService.addNotification(summary);
1217 mService.mAutobundledSummaries.put(0, new ArrayMap<>());
1218 mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
1219 mService.mSummaryByGroupKey.put("pkg", summary);
1220
Mady Mellor6d775f82019-11-12 16:12:19 -08001221 mService.updateAutobundledSummaryFlags(0, "pkg", false, false);
Jay Aliomerefe1c922019-09-19 16:42:16 -04001222
1223 assertFalse(summary.sbn.isOngoing());
1224 }
1225
1226 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001227 public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
1228 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001229 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001230 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1231 "testCancelAllNotifications_IgnoreForegroundService",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001232 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001233 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001234 waitForIdle();
1235 StatusBarNotification[] notifs =
1236 mBinderService.getActiveNotifications(sbn.getPackageName());
1237 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001238 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001239 }
1240
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001241 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001242 public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
1243 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldse5c60452018-04-30 14:41:36 -04001244 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001245 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1246 "testCancelAllNotifications_IgnoreOtherPackages",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001247 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001248 mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
1249 waitForIdle();
1250 StatusBarNotification[] notifs =
1251 mBinderService.getActiveNotifications(sbn.getPackageName());
1252 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
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001257 public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
1258 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001259 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1260 "testCancelAllNotifications_NullPkgRemovesAll",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001261 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001262 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1263 waitForIdle();
1264 StatusBarNotification[] notifs =
1265 mBinderService.getActiveNotifications(sbn.getPackageName());
1266 assertEquals(0, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001267 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001268 }
1269
Geoffrey Pitsch16594462017-01-26 14:42:30 -05001270 @Test
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001271 public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
1272 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001273 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1274 "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications",
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001275 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001276 // Null pkg is how we signal a user switch.
1277 mBinderService.cancelAllNotifications(null, sbn.getUserId());
1278 waitForIdle();
1279 StatusBarNotification[] notifs =
1280 mBinderService.getActiveNotifications(sbn.getPackageName());
1281 assertEquals(1, notifs.length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001282 assertEquals(1, mService.getNotificationRecordCount());
Geoffrey Pitsch331a64d2017-01-17 14:00:47 -05001283 }
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001284
1285 @Test
Beverly40239d92017-07-07 10:20:41 -04001286 public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1287 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1288 sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001289 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1290 "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag",
Beverly40239d92017-07-07 10:20:41 -04001291 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1292 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1293 waitForIdle();
1294 StatusBarNotification[] notifs =
1295 mBinderService.getActiveNotifications(sbn.getPackageName());
1296 assertEquals(0, notifs.length);
1297 }
1298
1299 @Test
1300 public void testCancelAllNotifications_CancelsNoClearFlag() throws Exception {
1301 final NotificationRecord notif = generateNotificationRecord(
1302 mTestNotificationChannel, 1, "group", true);
1303 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001304 mService.addNotification(notif);
1305 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
Beverly40239d92017-07-07 10:20:41 -04001306 notif.getUserId(), 0, null);
1307 waitForIdle();
1308 StatusBarNotification[] notifs =
1309 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1310 assertEquals(0, notifs.length);
1311 }
1312
1313 @Test
1314 public void testUserInitiatedCancelAllOnClearAll_NoClearFlag() throws Exception {
1315 final NotificationRecord notif = generateNotificationRecord(
1316 mTestNotificationChannel, 1, "group", true);
1317 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
Julia Reynolds503ed942017-10-04 16:04:56 -04001318 mService.addNotification(notif);
Beverly40239d92017-07-07 10:20:41 -04001319
Julia Reynolds503ed942017-10-04 16:04:56 -04001320 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001321 notif.getUserId());
1322 waitForIdle();
1323 StatusBarNotification[] notifs =
1324 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1325 assertEquals(1, notifs.length);
1326 }
1327
1328 @Test
1329 public void testCancelAllCancelNotificationsFromListener_NoClearFlag() throws Exception {
1330 final NotificationRecord parent = generateNotificationRecord(
1331 mTestNotificationChannel, 1, "group", true);
1332 final NotificationRecord child = generateNotificationRecord(
1333 mTestNotificationChannel, 2, "group", false);
1334 final NotificationRecord child2 = generateNotificationRecord(
1335 mTestNotificationChannel, 3, "group", false);
1336 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1337 final NotificationRecord newGroup = generateNotificationRecord(
1338 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001339 mService.addNotification(parent);
1340 mService.addNotification(child);
1341 mService.addNotification(child2);
1342 mService.addNotification(newGroup);
1343 mService.getBinderService().cancelNotificationsFromListener(null, null);
Beverly40239d92017-07-07 10:20:41 -04001344 waitForIdle();
1345 StatusBarNotification[] notifs =
1346 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1347 assertEquals(1, notifs.length);
1348 }
1349
1350 @Test
1351 public void testUserInitiatedCancelAllWithGroup_NoClearFlag() throws Exception {
1352 final NotificationRecord parent = generateNotificationRecord(
1353 mTestNotificationChannel, 1, "group", true);
1354 final NotificationRecord child = generateNotificationRecord(
1355 mTestNotificationChannel, 2, "group", false);
1356 final NotificationRecord child2 = generateNotificationRecord(
1357 mTestNotificationChannel, 3, "group", false);
1358 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1359 final NotificationRecord newGroup = generateNotificationRecord(
1360 mTestNotificationChannel, 4, "group2", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04001361 mService.addNotification(parent);
1362 mService.addNotification(child);
1363 mService.addNotification(child2);
1364 mService.addNotification(newGroup);
1365 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
Beverly40239d92017-07-07 10:20:41 -04001366 parent.getUserId());
1367 waitForIdle();
1368 StatusBarNotification[] notifs =
1369 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1370 assertEquals(1, notifs.length);
1371 }
1372
1373 @Test
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001374 public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001375 Notification n =
1376 new Notification.Builder(mContext, mTestNotificationChannel.getId())
1377 .setSmallIcon(android.R.drawable.sym_def_app_icon)
1378 .build();
1379 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0,
1380 n, new UserHandle(mUid), null, 0);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001381 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04001382 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001383 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001384 mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
1385 sbn.getUserId());
1386 waitForIdle();
1387 StatusBarNotification[] notifs =
1388 mBinderService.getActiveNotifications(sbn.getPackageName());
Julia Reynoldse5c60452018-04-30 14:41:36 -04001389 assertEquals(0, notifs[0].getNotification().flags & FLAG_FOREGROUND_SERVICE);
Geoffrey Pitsch415e4542017-04-10 13:12:58 -04001390 }
1391
1392 @Test
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001393 public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
1394 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1395 sbn.getNotification().flags =
Julia Reynoldse5c60452018-04-30 14:41:36 -04001396 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001397 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001398 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1399 sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001400 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001401 sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001402 mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(),
1403 sbn.getUserId());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001404 waitForIdle();
1405 assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
Julia Reynolds503ed942017-10-04 16:04:56 -04001406 assertEquals(0, mService.getNotificationRecordCount());
Geoffrey Pitsch27684152017-05-02 11:41:31 -04001407 }
1408
1409 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001410 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlag()
1411 throws Exception {
1412 final NotificationRecord parent = generateNotificationRecord(
1413 mTestNotificationChannel, 1, "group", true);
1414 final NotificationRecord child = generateNotificationRecord(
1415 mTestNotificationChannel, 2, "group", false);
1416 final NotificationRecord child2 = generateNotificationRecord(
1417 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001418 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001419 final NotificationRecord newGroup = generateNotificationRecord(
1420 mTestNotificationChannel, 4, "group2", false);
1421 mService.addNotification(parent);
1422 mService.addNotification(child);
1423 mService.addNotification(child2);
1424 mService.addNotification(newGroup);
1425 mService.getBinderService().cancelNotificationsFromListener(null, null);
1426 waitForIdle();
1427 StatusBarNotification[] notifs =
1428 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1429 assertEquals(0, notifs.length);
1430 }
1431
1432 @Test
1433 public void testCancelAllCancelNotificationsFromListener_ForegroundServiceFlagWithParameter()
1434 throws Exception {
1435 final NotificationRecord parent = generateNotificationRecord(
1436 mTestNotificationChannel, 1, "group", true);
1437 final NotificationRecord child = generateNotificationRecord(
1438 mTestNotificationChannel, 2, "group", false);
1439 final NotificationRecord child2 = generateNotificationRecord(
1440 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001441 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001442 final NotificationRecord newGroup = generateNotificationRecord(
1443 mTestNotificationChannel, 4, "group2", false);
1444 mService.addNotification(parent);
1445 mService.addNotification(child);
1446 mService.addNotification(child2);
1447 mService.addNotification(newGroup);
1448 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1449 child2.sbn.getKey(), newGroup.sbn.getKey()};
1450 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1451 waitForIdle();
1452 StatusBarNotification[] notifs =
1453 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1454 assertEquals(1, notifs.length);
1455 }
1456
1457 @Test
1458 public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
1459 final NotificationRecord parent = generateNotificationRecord(
1460 mTestNotificationChannel, 1, "group", true);
1461 final NotificationRecord child = generateNotificationRecord(
1462 mTestNotificationChannel, 2, "group", false);
1463 final NotificationRecord child2 = generateNotificationRecord(
1464 mTestNotificationChannel, 3, "group", false);
Julia Reynoldse5c60452018-04-30 14:41:36 -04001465 child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
Julia Reynolds40f00d72017-12-12 10:47:32 -05001466 final NotificationRecord newGroup = generateNotificationRecord(
1467 mTestNotificationChannel, 4, "group2", false);
1468 mService.addNotification(parent);
1469 mService.addNotification(child);
1470 mService.addNotification(child2);
1471 mService.addNotification(newGroup);
1472 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1473 parent.getUserId());
1474 waitForIdle();
1475 StatusBarNotification[] notifs =
1476 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1477 assertEquals(0, notifs.length);
1478 }
1479
1480 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001481 public void testFindGroupNotificationsLocked() throws Exception {
1482 // make sure the same notification can be found in both lists and returned
1483 final NotificationRecord group1 = generateNotificationRecord(
1484 mTestNotificationChannel, 1, "group1", true);
Julia Reynolds503ed942017-10-04 16:04:56 -04001485 mService.addEnqueuedNotification(group1);
1486 mService.addNotification(group1);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001487
1488 // should not be returned
1489 final NotificationRecord group2 = generateNotificationRecord(
1490 mTestNotificationChannel, 2, "group2", true);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001491 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001492 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
1493 waitForIdle();
1494
1495 // should not be returned
1496 final NotificationRecord nonGroup = generateNotificationRecord(
1497 mTestNotificationChannel, 3, null, false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001498 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001499 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
1500 waitForIdle();
1501
1502 // same group, child, should be returned
1503 final NotificationRecord group1Child = generateNotificationRecord(
1504 mTestNotificationChannel, 4, "group1", false);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001505 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked",
1506 group1Child.sbn.getId(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001507 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
1508 waitForIdle();
1509
1510 List<NotificationRecord> inGroup1 =
Julia Reynolds503ed942017-10-04 16:04:56 -04001511 mService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001512 group1.sbn.getUserId());
1513 assertEquals(3, inGroup1.size());
1514 for (NotificationRecord record : inGroup1) {
1515 assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
1516 assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
1517 }
1518 }
1519
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04001520 @Test
Julia Reynolds40f00d72017-12-12 10:47:32 -05001521 public void testCancelAllNotifications_CancelsNoClearFlagOnGoing() throws Exception {
1522 final NotificationRecord notif = generateNotificationRecord(
1523 mTestNotificationChannel, 1, "group", true);
1524 notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1525 mService.addNotification(notif);
1526 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
1527 Notification.FLAG_ONGOING_EVENT, true, notif.getUserId(), 0, null);
1528 waitForIdle();
1529 StatusBarNotification[] notifs =
1530 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1531 assertEquals(0, notifs.length);
1532 }
1533
1534 @Test
1535 public void testCancelAllCancelNotificationsFromListener_NoClearFlagWithParameter()
1536 throws Exception {
1537 final NotificationRecord parent = generateNotificationRecord(
1538 mTestNotificationChannel, 1, "group", true);
1539 final NotificationRecord child = generateNotificationRecord(
1540 mTestNotificationChannel, 2, "group", false);
1541 final NotificationRecord child2 = generateNotificationRecord(
1542 mTestNotificationChannel, 3, "group", false);
1543 child2.getNotification().flags |= Notification.FLAG_NO_CLEAR;
1544 final NotificationRecord newGroup = generateNotificationRecord(
1545 mTestNotificationChannel, 4, "group2", false);
1546 mService.addNotification(parent);
1547 mService.addNotification(child);
1548 mService.addNotification(child2);
1549 mService.addNotification(newGroup);
1550 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1551 child2.sbn.getKey(), newGroup.sbn.getKey()};
1552 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1553 waitForIdle();
1554 StatusBarNotification[] notifs =
1555 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1556 assertEquals(0, notifs.length);
1557 }
1558
1559 @Test
1560 public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1561 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
1562 sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001563 mBinderService.enqueueNotificationWithTag(PKG, PKG,
1564 "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag",
Julia Reynolds40f00d72017-12-12 10:47:32 -05001565 sbn.getId(), sbn.getNotification(), sbn.getUserId());
1566 mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
1567 waitForIdle();
1568 StatusBarNotification[] notifs =
1569 mBinderService.getActiveNotifications(sbn.getPackageName());
1570 assertEquals(0, notifs.length);
1571 }
1572
1573 @Test
1574 public void testCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
1575 final NotificationRecord notif = generateNotificationRecord(
1576 mTestNotificationChannel, 1, "group", true);
1577 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1578 mService.addNotification(notif);
1579 mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0, true,
1580 notif.getUserId(), 0, null);
1581 waitForIdle();
1582 StatusBarNotification[] notifs =
1583 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1584 assertEquals(0, notifs.length);
1585 }
1586
1587 @Test
1588 public void testUserInitiatedCancelAllOnClearAll_OnGoingFlag() throws Exception {
1589 final NotificationRecord notif = generateNotificationRecord(
1590 mTestNotificationChannel, 1, "group", true);
1591 notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1592 mService.addNotification(notif);
1593
1594 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1595 notif.getUserId());
1596 waitForIdle();
1597 StatusBarNotification[] notifs =
1598 mBinderService.getActiveNotifications(notif.sbn.getPackageName());
1599 assertEquals(1, notifs.length);
1600 }
1601
1602 @Test
1603 public void testCancelAllCancelNotificationsFromListener_OnGoingFlag() throws Exception {
1604 final NotificationRecord parent = generateNotificationRecord(
1605 mTestNotificationChannel, 1, "group", true);
1606 final NotificationRecord child = generateNotificationRecord(
1607 mTestNotificationChannel, 2, "group", false);
1608 final NotificationRecord child2 = generateNotificationRecord(
1609 mTestNotificationChannel, 3, "group", false);
1610 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1611 final NotificationRecord newGroup = generateNotificationRecord(
1612 mTestNotificationChannel, 4, "group2", false);
1613 mService.addNotification(parent);
1614 mService.addNotification(child);
1615 mService.addNotification(child2);
1616 mService.addNotification(newGroup);
1617 mService.getBinderService().cancelNotificationsFromListener(null, null);
1618 waitForIdle();
1619 StatusBarNotification[] notifs =
1620 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1621 assertEquals(1, notifs.length);
1622 }
1623
1624 @Test
1625 public void testCancelAllCancelNotificationsFromListener_OnGoingFlagWithParameter()
1626 throws Exception {
1627 final NotificationRecord parent = generateNotificationRecord(
1628 mTestNotificationChannel, 1, "group", true);
1629 final NotificationRecord child = generateNotificationRecord(
1630 mTestNotificationChannel, 2, "group", false);
1631 final NotificationRecord child2 = generateNotificationRecord(
1632 mTestNotificationChannel, 3, "group", false);
1633 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1634 final NotificationRecord newGroup = generateNotificationRecord(
1635 mTestNotificationChannel, 4, "group2", false);
1636 mService.addNotification(parent);
1637 mService.addNotification(child);
1638 mService.addNotification(child2);
1639 mService.addNotification(newGroup);
1640 String[] keys = {parent.sbn.getKey(), child.sbn.getKey(),
1641 child2.sbn.getKey(), newGroup.sbn.getKey()};
1642 mService.getBinderService().cancelNotificationsFromListener(null, keys);
1643 waitForIdle();
1644 StatusBarNotification[] notifs =
1645 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1646 assertEquals(0, notifs.length);
1647 }
1648
1649 @Test
1650 public void testUserInitiatedCancelAllWithGroup_OnGoingFlag() throws Exception {
1651 final NotificationRecord parent = generateNotificationRecord(
1652 mTestNotificationChannel, 1, "group", true);
1653 final NotificationRecord child = generateNotificationRecord(
1654 mTestNotificationChannel, 2, "group", false);
1655 final NotificationRecord child2 = generateNotificationRecord(
1656 mTestNotificationChannel, 3, "group", false);
1657 child2.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
1658 final NotificationRecord newGroup = generateNotificationRecord(
1659 mTestNotificationChannel, 4, "group2", false);
1660 mService.addNotification(parent);
1661 mService.addNotification(child);
1662 mService.addNotification(child2);
1663 mService.addNotification(newGroup);
1664 mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
1665 parent.getUserId());
1666 waitForIdle();
1667 StatusBarNotification[] notifs =
1668 mBinderService.getActiveNotifications(parent.sbn.getPackageName());
1669 assertEquals(1, notifs.length);
1670 }
1671
1672 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001673 public void testTvExtenderChannelOverride_onTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001674 mService.setIsTelevision(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001675 mService.setPreferencesHelper(mPreferencesHelper);
1676 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001677 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001678 new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001679
Julia Reynoldsbad42972017-04-25 13:52:49 -04001680 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001681 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0,
Julia Reynoldsfea6f7b2017-04-19 13:50:12 -04001682 generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001683 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001684 anyString(), anyInt(), eq("foo"), anyBoolean());
1685 }
1686
1687 @Test
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001688 public void testTvExtenderChannelOverride_notOnTv() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04001689 mService.setIsTelevision(false);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001690 mService.setPreferencesHelper(mPreferencesHelper);
1691 when(mPreferencesHelper.getNotificationChannel(
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001692 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001693 mTestNotificationChannel);
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001694
Julia Reynoldsbad42972017-04-25 13:52:49 -04001695 Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
Julia Reynoldsb6c83742019-07-30 18:03:40 -04001696 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv",
1697 0, generateNotificationRecord(null, tv).getNotification(), 0);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001698 verify(mPreferencesHelper, times(1)).getNotificationChannel(
Geoffrey Pitsch1f17e022017-01-03 16:44:20 -05001699 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
Julia Reynolds5f20e9f2017-01-30 08:54:53 -05001700 }
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001701
1702 @Test
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001703 public void testUpdateAppNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001704 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001705
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001706 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001707 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1708 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1709
1710 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1711 captor.getValue().getAction());
1712 assertEquals(PKG, captor.getValue().getPackage());
Julia Reynoldsc4c6e9f2019-06-03 12:48:49 -04001713 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1714 }
1715
1716 @Test
1717 public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
1718 mService.setPreferencesHelper(mPreferencesHelper);
1719
1720 mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
1721 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001722 }
1723
1724 @Test
1725 public void testUpdateAppNotifyCreatorUnblock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001726 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsfc9767b2018-01-22 17:45:16 -05001727
1728 mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
1729 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1730 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1731
1732 assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
1733 captor.getValue().getAction());
1734 assertEquals(PKG, captor.getValue().getPackage());
1735 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
1736 }
1737
1738 @Test
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001739 public void testUpdateChannelNotifyCreatorBlock() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001740 mService.setPreferencesHelper(mPreferencesHelper);
1741 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001742 eq(mTestNotificationChannel.getId()), anyBoolean()))
1743 .thenReturn(mTestNotificationChannel);
1744
1745 NotificationChannel updatedChannel =
1746 new NotificationChannel(mTestNotificationChannel.getId(),
1747 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
1748
1749 mBinderService.updateNotificationChannelForPackage(PKG, 0, updatedChannel);
1750 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1751 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1752
1753 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1754 captor.getValue().getAction());
1755 assertEquals(PKG, captor.getValue().getPackage());
1756 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001757 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001758 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1759 }
1760
1761 @Test
1762 public void testUpdateChannelNotifyCreatorUnblock() throws Exception {
1763 NotificationChannel existingChannel =
1764 new NotificationChannel(mTestNotificationChannel.getId(),
1765 mTestNotificationChannel.getName(), IMPORTANCE_NONE);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001766 mService.setPreferencesHelper(mPreferencesHelper);
1767 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001768 eq(mTestNotificationChannel.getId()), anyBoolean()))
1769 .thenReturn(existingChannel);
1770
1771 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1772 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1773 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1774
1775 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED,
1776 captor.getValue().getAction());
1777 assertEquals(PKG, captor.getValue().getPackage());
1778 assertEquals(mTestNotificationChannel.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001779 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001780 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1781 }
1782
1783 @Test
1784 public void testUpdateChannelNoNotifyCreatorOtherChanges() throws Exception {
1785 NotificationChannel existingChannel =
1786 new NotificationChannel(mTestNotificationChannel.getId(),
1787 mTestNotificationChannel.getName(), IMPORTANCE_MAX);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001788 mService.setPreferencesHelper(mPreferencesHelper);
1789 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001790 eq(mTestNotificationChannel.getId()), anyBoolean()))
1791 .thenReturn(existingChannel);
1792
1793 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
1794 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1795 }
1796
1797 @Test
1798 public void testUpdateGroupNotifyCreatorBlock() throws Exception {
1799 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001800 mService.setPreferencesHelper(mPreferencesHelper);
1801 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001802 .thenReturn(existing);
1803
1804 NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
1805 updated.setBlocked(true);
1806
1807 mBinderService.updateNotificationChannelGroupForPackage(PKG, 0, updated);
1808 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1809 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1810
1811 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1812 captor.getValue().getAction());
1813 assertEquals(PKG, captor.getValue().getPackage());
1814 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001815 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001816 assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1817 }
1818
1819 @Test
1820 public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
1821 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
1822 existing.setBlocked(true);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001823 mService.setPreferencesHelper(mPreferencesHelper);
1824 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001825 .thenReturn(existing);
1826
1827 mBinderService.updateNotificationChannelGroupForPackage(
1828 PKG, 0, new NotificationChannelGroup("id", "name"));
1829 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
1830 verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
1831
1832 assertEquals(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED,
1833 captor.getValue().getAction());
1834 assertEquals(PKG, captor.getValue().getPackage());
1835 assertEquals(existing.getId(), captor.getValue().getStringExtra(
Julia Reynolds44ff7c92018-02-05 10:02:30 -05001836 NotificationManager.EXTRA_NOTIFICATION_CHANNEL_GROUP_ID));
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001837 assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
1838 }
1839
1840 @Test
1841 public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
1842 NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001843 mService.setPreferencesHelper(mPreferencesHelper);
1844 when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001845 .thenReturn(existing);
1846
1847 mBinderService.updateNotificationChannelGroupForPackage(
1848 PKG, 0, new NotificationChannelGroup("id", "new name"));
1849 verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
1850 }
1851
1852 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001853 public void testCreateChannelNotifyListener() throws Exception {
1854 List<String> associations = new ArrayList<>();
1855 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001856 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001857 mService.setPreferencesHelper(mPreferencesHelper);
1858 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001859 eq(mTestNotificationChannel.getId()), anyBoolean()))
1860 .thenReturn(mTestNotificationChannel);
1861 NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001862 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001863 eq(channel2.getId()), anyBoolean()))
1864 .thenReturn(channel2);
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001865 when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
1866 eq(channel2), anyBoolean(), anyBoolean()))
1867 .thenReturn(true);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001868
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001869 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001870 mBinderService.createNotificationChannels(PKG,
1871 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
Julia Reynoldsdafd3a42019-05-24 13:33:28 -04001872 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001873 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001874 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001875 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001876 eq(Process.myUserHandle()), eq(channel2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001877 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1878 }
1879
1880 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001881 public void testCreateChannelGroupNotifyListener() throws Exception {
1882 List<String> associations = new ArrayList<>();
1883 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001884 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001885 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001886 NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
1887 NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
1888
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001889 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001890 mBinderService.createNotificationChannelGroups(PKG,
1891 new ParceledListSlice(Arrays.asList(group1, group2)));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001892 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001893 eq(Process.myUserHandle()), eq(group1),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001894 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001895 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001896 eq(Process.myUserHandle()), eq(group2),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001897 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
1898 }
1899
1900 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001901 public void testUpdateChannelNotifyListener() throws Exception {
1902 List<String> associations = new ArrayList<>();
1903 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001904 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001905 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001906 mTestNotificationChannel.setLightColor(Color.CYAN);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001907 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001908 eq(mTestNotificationChannel.getId()), anyBoolean()))
1909 .thenReturn(mTestNotificationChannel);
1910
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001911 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001912 mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001913 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001914 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001915 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1916 }
1917
1918 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001919 public void testDeleteChannelNotifyListener() throws Exception {
1920 List<String> associations = new ArrayList<>();
1921 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001922 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001923 mService.setPreferencesHelper(mPreferencesHelper);
1924 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001925 eq(mTestNotificationChannel.getId()), anyBoolean()))
1926 .thenReturn(mTestNotificationChannel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001927 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001928 mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001929 verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001930 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001931 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1932 }
1933
1934 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001935 public void testDeleteChannelGroupNotifyListener() throws Exception {
1936 List<String> associations = new ArrayList<>();
1937 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001938 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001939 NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001940 mService.setPreferencesHelper(mPreferencesHelper);
1941 when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001942 .thenReturn(ncg);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001943 reset(mListeners);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001944 mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001945 verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001946 eq(Process.myUserHandle()), eq(ncg),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001947 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
1948 }
1949
1950 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001951 public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001952 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001953 List<String> associations = new ArrayList<>();
1954 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001955 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001956 when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
Julia Reynolds3eb3ffd2017-11-16 10:11:32 -05001957 eq(mTestNotificationChannel.getId()), anyBoolean()))
1958 .thenReturn(mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001959
1960 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001961 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001962
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001963 verify(mPreferencesHelper, times(1)).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001964 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001965
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001966 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001967 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001968 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1969 }
1970
1971 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001972 public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001973 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001974 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001975 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001976
1977 try {
1978 mBinderService.updateNotificationChannelFromPrivilegedListener(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001979 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001980 fail("listeners that don't have a companion device shouldn't be able to call this");
1981 } catch (SecurityException e) {
1982 // pass
1983 }
1984
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001985 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04001986 anyString(), anyInt(), any(), anyBoolean());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04001987
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04001988 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001989 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
1990 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
1991 }
1992
1993 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001994 public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04001995 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001996 List<String> associations = new ArrayList<>();
1997 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04001998 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04001999 mListener = mock(ManagedServices.ManagedServiceInfo.class);
Julia Reynolds4da79702017-06-01 11:06:10 -04002000 mListener.component = new ComponentName(PKG, PKG);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002001 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002002 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002003
2004 try {
2005 mBinderService.updateNotificationChannelFromPrivilegedListener(
2006 null, PKG, UserHandle.ALL, mTestNotificationChannel);
2007 fail("incorrectly allowed a change to a user listener cannot see");
2008 } catch (SecurityException e) {
2009 // pass
2010 }
2011
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002012 verify(mPreferencesHelper, never()).updateNotificationChannel(
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002013 anyString(), anyInt(), any(), anyBoolean());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002014
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002015 verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002016 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002017 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
2018 }
2019
2020 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002021 public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002022 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002023 List<String> associations = new ArrayList<>();
2024 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002025 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002026
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002027 mBinderService.getNotificationChannelsFromPrivilegedListener(
2028 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002029
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002030 verify(mPreferencesHelper, times(1)).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002031 anyString(), anyInt(), anyBoolean());
2032 }
2033
2034 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002035 public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002036 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002037 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002038 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002039
2040 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002041 mBinderService.getNotificationChannelsFromPrivilegedListener(
2042 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002043 fail("listeners that don't have a companion device shouldn't be able to call this");
2044 } catch (SecurityException e) {
2045 // pass
2046 }
2047
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002048 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002049 anyString(), anyInt(), anyBoolean());
2050 }
2051
2052 @Test
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002053 public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
2054 throws Exception {
2055 mService.setPreferencesHelper(mPreferencesHelper);
2056 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2057 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
2058
2059 mBinderService.getNotificationChannelsFromPrivilegedListener(
2060 null, PKG, Process.myUserHandle());
2061
2062 verify(mPreferencesHelper, times(1)).getNotificationChannels(
2063 anyString(), anyInt(), anyBoolean());
2064 }
2065
2066 @Test
Julia Reynolds268647a2018-10-25 16:54:27 -04002067 public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
2068 throws Exception {
Julia Reynolds48a6ed92018-10-22 12:52:03 -04002069 mService.setPreferencesHelper(mPreferencesHelper);
2070 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
2071 when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
2072
2073 try {
2074 mBinderService.getNotificationChannelsFromPrivilegedListener(
2075 null, PKG, Process.myUserHandle());
2076 fail("listeners that don't have a companion device shouldn't be able to call this");
2077 } catch (SecurityException e) {
2078 // pass
2079 }
2080
2081 verify(mPreferencesHelper, never()).getNotificationChannels(
2082 anyString(), anyInt(), anyBoolean());
2083 }
2084
2085 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002086 public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002087 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002088 List<String> associations = new ArrayList<>();
2089 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002090 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002091 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2092 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002093 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002094
2095 try {
2096 mBinderService.getNotificationChannelsFromPrivilegedListener(
2097 null, PKG, Process.myUserHandle());
2098 fail("listener getting channels from a user they cannot see");
2099 } catch (SecurityException e) {
2100 // pass
2101 }
2102
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002103 verify(mPreferencesHelper, never()).getNotificationChannels(
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002104 anyString(), anyInt(), anyBoolean());
2105 }
2106
2107 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002108 public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002109 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002110 List<String> associations = new ArrayList<>();
2111 associations.add("a");
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002112 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002113
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002114 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2115 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002116
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002117 verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002118 }
2119
2120 @Test
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002121 public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002122 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002123 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002124 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002125
2126 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002127 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2128 null, PKG, Process.myUserHandle());
2129 fail("listeners that don't have a companion device shouldn't be able to call this");
2130 } catch (SecurityException e) {
2131 // pass
2132 }
2133
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002134 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002135 }
2136
2137 @Test
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002138 public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002139 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002140 List<String> associations = new ArrayList<>();
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002141 when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002142 mListener = mock(ManagedServices.ManagedServiceInfo.class);
2143 when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002144 when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
Julia Reynolds27c0a962018-12-10 12:37:28 -05002145 try {
Julia Reynoldsf27d6b22017-04-13 15:48:16 -04002146 mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
2147 null, PKG, Process.myUserHandle());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002148 fail("listeners that don't have a companion device shouldn't be able to call this");
2149 } catch (SecurityException e) {
2150 // pass
2151 }
2152
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002153 verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
Julia Reynolds73ed76b2017-04-04 17:04:38 -04002154 }
Julia Reynoldsda781472017-04-12 09:41:16 -04002155
2156 @Test
Julia Reynoldsda781472017-04-12 09:41:16 -04002157 public void testHasCompanionDevice_failure() throws Exception {
2158 when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
2159 new IllegalArgumentException());
Julia Reynolds503ed942017-10-04 16:04:56 -04002160 mService.hasCompanionDevice(mListener);
Julia Reynoldsda781472017-04-12 09:41:16 -04002161 }
Julia Reynolds727a7282017-04-13 10:54:01 -04002162
2163 @Test
Julia Reynolds0c245002019-03-27 16:10:11 -04002164 public void testHasCompanionDevice_noService() {
2165 mService = new TestableNotificationManagerService(mContext);
Julia Reynolds727a7282017-04-13 10:54:01 -04002166
Julia Reynolds503ed942017-10-04 16:04:56 -04002167 assertFalse(mService.hasCompanionDevice(mListener));
Julia Reynolds727a7282017-04-13 10:54:01 -04002168 }
2169
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002170 @Test
Jay Aliomer24642da2019-07-30 09:57:41 -04002171 public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
2172 final NotificationRecord notification = generateNotificationRecord(
2173 mTestNotificationChannel, 1, null, true);
2174 mService.addNotification(notification);
2175 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2176
2177 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2178 mService.new SnoozeNotificationRunnable(
2179 notification.getKey(), 100, null);
2180 snoozeNotificationRunnable.run();
2181 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2182 mService.new SnoozeNotificationRunnable(
2183 notification.getKey(), 100, null);
2184 snoozeNotificationRunnable.run();
2185
2186 // snooze twice
2187 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2188 }
2189
2190 @Test
2191 public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
2192 final NotificationRecord notification = generateNotificationRecord(
2193 mTestNotificationChannel, 1, "group", true);
2194 mService.addNotification(notification);
2195 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2196
2197 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2198 mService.new SnoozeNotificationRunnable(
2199 notification.getKey(), 100, null);
2200 snoozeNotificationRunnable.run();
2201 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2202 mService.new SnoozeNotificationRunnable(
2203 notification.getKey(), 100, null);
2204 snoozeNotificationRunnable.run();
2205
2206 // snooze twice
2207 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2208 }
2209
2210 @Test
2211 public void testSnoozeRunnable_reSnoozeMultipleNotificationsWithGroupKey() throws Exception {
2212 final NotificationRecord notification = generateNotificationRecord(
2213 mTestNotificationChannel, 1, "group", true);
2214 final NotificationRecord notification2 = generateNotificationRecord(
2215 mTestNotificationChannel, 2, "group", true);
2216 mService.addNotification(notification);
2217 mService.addNotification(notification2);
2218 when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
2219 when(mSnoozeHelper.getNotifications(
2220 anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
2221
2222 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
2223 mService.new SnoozeNotificationRunnable(
2224 notification.getKey(), 100, null);
2225 snoozeNotificationRunnable.run();
2226 when(mSnoozeHelper.getNotifications(anyString(), anyString(), anyInt()))
2227 .thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
2228 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
2229 mService.new SnoozeNotificationRunnable(
2230 notification.getKey(), 100, null);
2231 snoozeNotificationRunnable.run();
2232
2233 // snooze twice
2234 verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
2235 }
2236
2237 @Test
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002238 public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
2239 final NotificationRecord nonGrouped = generateNotificationRecord(
2240 mTestNotificationChannel, 1, null, false);
2241 final NotificationRecord grouped = generateNotificationRecord(
2242 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002243 mService.addNotification(grouped);
2244 mService.addNotification(nonGrouped);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002245
2246 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002247 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002248 nonGrouped.getKey(), 100, null);
2249 snoozeNotificationRunnable.run();
2250
2251 // only snooze the one notification
2252 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
Julia Reynolds503ed942017-10-04 16:04:56 -04002253 assertTrue(nonGrouped.getStats().hasSnoozed());
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002254 }
2255
2256 @Test
2257 public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
2258 final NotificationRecord parent = generateNotificationRecord(
2259 mTestNotificationChannel, 1, "group", true);
2260 final NotificationRecord child = generateNotificationRecord(
2261 mTestNotificationChannel, 2, "group", false);
2262 final NotificationRecord child2 = generateNotificationRecord(
2263 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002264 mService.addNotification(parent);
2265 mService.addNotification(child);
2266 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002267
2268 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002269 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002270 parent.getKey(), 100, null);
2271 snoozeNotificationRunnable.run();
2272
2273 // snooze parent and children
2274 verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
2275 }
2276
2277 @Test
2278 public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
2279 final NotificationRecord parent = generateNotificationRecord(
2280 mTestNotificationChannel, 1, "group", true);
2281 final NotificationRecord child = generateNotificationRecord(
2282 mTestNotificationChannel, 2, "group", false);
2283 final NotificationRecord child2 = generateNotificationRecord(
2284 mTestNotificationChannel, 3, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002285 mService.addNotification(parent);
2286 mService.addNotification(child);
2287 mService.addNotification(child2);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002288
2289 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002290 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002291 child2.getKey(), 100, null);
2292 snoozeNotificationRunnable.run();
2293
2294 // only snooze the one child
2295 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2296 }
2297
2298 @Test
2299 public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
2300 final NotificationRecord parent = generateNotificationRecord(
2301 mTestNotificationChannel, 1, "group", true);
2302 assertTrue(parent.sbn.getNotification().isGroupSummary());
2303 final NotificationRecord child = generateNotificationRecord(
2304 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002305 mService.addNotification(parent);
2306 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002307
2308 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002309 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002310 child.getKey(), 100, null);
2311 snoozeNotificationRunnable.run();
2312
2313 // snooze child and summary
2314 verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
2315 }
2316
2317 @Test
2318 public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
2319 final NotificationRecord child = generateNotificationRecord(
2320 mTestNotificationChannel, 2, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002321 mService.addNotification(child);
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002322
2323 NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002324 mService.new SnoozeNotificationRunnable(
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002325 child.getKey(), 100, null);
2326 snoozeNotificationRunnable.run();
2327
2328 // snooze child only
2329 verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
2330 }
2331
2332 @Test
2333 public void testPostGroupChild_unsnoozeParent() throws Exception {
2334 final NotificationRecord child = generateNotificationRecord(
2335 mTestNotificationChannel, 2, "group", false);
2336
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002337 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002338 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
2339 waitForIdle();
2340
2341 verify(mSnoozeHelper, times(1)).repostGroupSummary(
2342 anyString(), anyInt(), eq(child.getGroupKey()));
2343 }
2344
2345 @Test
2346 public void testPostNonGroup_noUnsnoozing() throws Exception {
2347 final NotificationRecord record = generateNotificationRecord(
2348 mTestNotificationChannel, 2, null, false);
2349
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002350 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002351 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
2352 waitForIdle();
2353
2354 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2355 }
2356
2357 @Test
2358 public void testPostGroupSummary_noUnsnoozing() throws Exception {
2359 final NotificationRecord parent = generateNotificationRecord(
2360 mTestNotificationChannel, 2, "group", true);
2361
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002362 mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing",
Julia Reynoldsa78cdff2017-04-26 10:19:25 -04002363 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
2364 waitForIdle();
2365
2366 verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
2367 }
Julia Reynoldsb852e562017-06-06 16:14:18 -04002368
2369 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002370 public void testSetListenerAccessForUser() throws Exception {
2371 UserHandle user = UserHandle.of(10);
2372 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002373 mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
2374
Julia Reynolds92febc32017-10-26 11:30:31 -04002375
2376 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2377 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2378 c.flattenToString(), user.getIdentifier(), true, true);
2379 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2380 c.flattenToString(), user.getIdentifier(), false, true);
2381 verify(mAssistants, never()).setPackageOrComponentEnabled(
2382 any(), anyInt(), anyBoolean(), anyBoolean());
2383 }
2384
2385 @Test
2386 public void testSetAssistantAccessForUser() throws Exception {
2387 UserHandle user = UserHandle.of(10);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002388 List<UserInfo> uis = new ArrayList<>();
2389 UserInfo ui = new UserInfo();
2390 ui.id = 10;
2391 uis.add(ui);
Julia Reynolds92febc32017-10-26 11:30:31 -04002392 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002393 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
2394
2395 mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002396
2397 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2398 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2399 c.flattenToString(), user.getIdentifier(), true, true);
Tony Mak9a3c1f12019-03-04 16:04:42 +00002400 verify(mAssistants).setUserSet(10, true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002401 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2402 c.flattenToString(), user.getIdentifier(), false, true);
2403 verify(mListeners, never()).setPackageOrComponentEnabled(
2404 any(), anyInt(), anyBoolean(), anyBoolean());
2405 }
2406
2407 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002408 public void testGetAssistantAllowedForUser() throws Exception {
2409 UserHandle user = UserHandle.of(10);
2410 try {
2411 mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
2412 } catch (IllegalStateException e) {
2413 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2414 throw e;
2415 }
2416 }
2417 verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
2418 }
2419
2420 @Test
2421 public void testGetAssistantAllowed() throws Exception {
2422 try {
2423 mBinderService.getAllowedNotificationAssistant();
2424 } catch (IllegalStateException e) {
2425 if (!e.getMessage().contains("At most one NotificationAssistant")) {
2426 throw e;
2427 }
2428 }
2429 verify(mAssistants, times(1)).getAllowedComponents(0);
2430 }
2431
2432 @Test
Julia Reynolds92febc32017-10-26 11:30:31 -04002433 public void testSetDndAccessForUser() throws Exception {
2434 UserHandle user = UserHandle.of(10);
2435 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002436 mBinderService.setNotificationPolicyAccessGrantedForUser(
2437 c.getPackageName(), user.getIdentifier(), true);
Julia Reynolds92febc32017-10-26 11:30:31 -04002438
2439 verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
2440 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2441 c.getPackageName(), user.getIdentifier(), true, true);
2442 verify(mAssistants, never()).setPackageOrComponentEnabled(
2443 any(), anyInt(), anyBoolean(), anyBoolean());
2444 verify(mListeners, never()).setPackageOrComponentEnabled(
2445 any(), anyInt(), anyBoolean(), anyBoolean());
2446 }
2447
2448 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002449 public void testSetListenerAccess() throws Exception {
2450 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002451 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002452
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002453 verify(mListeners, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002454 c.flattenToString(), 0, true, true);
2455 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2456 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002457 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002458 any(), anyInt(), anyBoolean(), anyBoolean());
2459 }
2460
2461 @Test
2462 public void testSetAssistantAccess() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002463 List<UserInfo> uis = new ArrayList<>();
2464 UserInfo ui = new UserInfo();
2465 ui.id = 0;
2466 uis.add(ui);
2467 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002468 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002469
2470 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002471
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002472 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002473 c.flattenToString(), 0, true, true);
2474 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2475 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002476 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002477 any(), anyInt(), anyBoolean(), anyBoolean());
2478 }
2479
2480 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002481 public void testSetAssistantAccess_multiProfile() throws Exception {
2482 List<UserInfo> uis = new ArrayList<>();
2483 UserInfo ui = new UserInfo();
2484 ui.id = 0;
2485 uis.add(ui);
2486 UserInfo ui10 = new UserInfo();
2487 ui10.id = 10;
2488 uis.add(ui10);
2489 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2490 ComponentName c = ComponentName.unflattenFromString("package/Component");
2491
2492 mBinderService.setNotificationAssistantAccessGranted(c, true);
2493
2494 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2495 c.flattenToString(), 0, true, true);
2496 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2497 c.flattenToString(), 10, true, true);
2498 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2499 c.flattenToString(), 0, false, true);
2500 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2501 c.flattenToString(), 10, false, true);
2502 verify(mListeners, never()).setPackageOrComponentEnabled(
2503 any(), anyInt(), anyBoolean(), anyBoolean());
2504 }
2505
2506 @Test
Fabian Kozynskid9425662019-01-29 13:08:30 -05002507 public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
2508 ArrayList<ComponentName> componentList = new ArrayList<>();
2509 ComponentName c = ComponentName.unflattenFromString("package/Component");
2510 componentList.add(c);
2511 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002512 List<UserInfo> uis = new ArrayList<>();
2513 UserInfo ui = new UserInfo();
2514 ui.id = 0;
2515 uis.add(ui);
2516 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002517
Julia Reynolds4afe2642019-05-01 08:42:24 -04002518 mBinderService.setNotificationAssistantAccessGranted(null, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002519
2520 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2521 c.flattenToString(), 0, true, false);
2522 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2523 c.flattenToString(), 0, false, false);
2524 verify(mListeners, never()).setPackageOrComponentEnabled(
2525 any(), anyInt(), anyBoolean(), anyBoolean());
2526 }
2527
2528 @Test
2529 public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
Julia Reynolds4afe2642019-05-01 08:42:24 -04002530 List<UserInfo> uis = new ArrayList<>();
2531 UserInfo ui = new UserInfo();
2532 ui.id = 10;
2533 uis.add(ui);
2534 UserHandle user = ui.getUserHandle();
Fabian Kozynskid9425662019-01-29 13:08:30 -05002535 ArrayList<ComponentName> componentList = new ArrayList<>();
2536 ComponentName c = ComponentName.unflattenFromString("package/Component");
2537 componentList.add(c);
2538 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002539 when(mUm.getEnabledProfiles(10)).thenReturn(uis);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002540
Julia Reynolds4afe2642019-05-01 08:42:24 -04002541 mBinderService.setNotificationAssistantAccessGrantedForUser(
2542 null, user.getIdentifier(), true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002543
2544 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2545 c.flattenToString(), user.getIdentifier(), true, false);
Julia Reynolds4afe2642019-05-01 08:42:24 -04002546 verify(mAssistants).setUserSet(10, true);
Fabian Kozynskid9425662019-01-29 13:08:30 -05002547 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2548 c.flattenToString(), user.getIdentifier(), false, false);
2549 verify(mListeners, never()).setPackageOrComponentEnabled(
2550 any(), anyInt(), anyBoolean(), anyBoolean());
2551 }
2552
2553 @Test
Julia Reynolds4afe2642019-05-01 08:42:24 -04002554 public void testSetAssistantAccessForUser_workProfile_nullWithAllowedAssistant()
2555 throws Exception {
2556 List<UserInfo> uis = new ArrayList<>();
2557 UserInfo ui = new UserInfo();
2558 ui.id = 0;
2559 uis.add(ui);
2560 UserInfo ui10 = new UserInfo();
2561 ui10.id = 10;
2562 uis.add(ui10);
2563 UserHandle user = ui.getUserHandle();
2564 ArrayList<ComponentName> componentList = new ArrayList<>();
2565 ComponentName c = ComponentName.unflattenFromString("package/Component");
2566 componentList.add(c);
2567 when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
2568 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2569
2570 mBinderService.setNotificationAssistantAccessGrantedForUser(
2571 null, user.getIdentifier(), true);
2572
2573 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2574 c.flattenToString(), user.getIdentifier(), true, false);
2575 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2576 c.flattenToString(), ui10.id, true, false);
2577 verify(mAssistants).setUserSet(0, true);
2578 verify(mAssistants).setUserSet(10, true);
2579 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2580 c.flattenToString(), user.getIdentifier(), false, false);
2581 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2582 c.flattenToString(), ui10.id, false, false);
2583 verify(mListeners, never()).setPackageOrComponentEnabled(
2584 any(), anyInt(), anyBoolean(), anyBoolean());
2585 }
2586
2587 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -04002588 public void testSetDndAccess() throws Exception {
2589 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002590
2591 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldsb852e562017-06-06 16:14:18 -04002592
2593 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2594 c.getPackageName(), 0, true, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002595 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002596 any(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002597 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldsb852e562017-06-06 16:14:18 -04002598 any(), anyInt(), anyBoolean(), anyBoolean());
2599 }
Julia Reynolds68263d12017-06-21 14:21:19 -04002600
2601 @Test
2602 public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
2603 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2604 ComponentName c = ComponentName.unflattenFromString("package/Component");
2605 mBinderService.setNotificationListenerAccessGranted(c, true);
2606
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002607 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002608 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002609 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002610 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002611 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002612 any(), anyInt(), anyBoolean(), anyBoolean());
2613 }
2614
2615 @Test
2616 public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
2617 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2618 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002619 List<UserInfo> uis = new ArrayList<>();
2620 UserInfo ui = new UserInfo();
2621 ui.id = 0;
2622 uis.add(ui);
2623 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2624
Julia Reynolds68263d12017-06-21 14:21:19 -04002625 mBinderService.setNotificationAssistantAccessGranted(c, true);
2626
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002627 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002628 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002629 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002630 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002631 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002632 any(), anyInt(), anyBoolean(), anyBoolean());
2633 }
2634
2635 @Test
2636 public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
2637 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2638 ComponentName c = ComponentName.unflattenFromString("package/Component");
2639 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
2640
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002641 verify(mListeners, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002642 anyString(), anyInt(), anyBoolean(), anyBoolean());
Julia Reynolds68263d12017-06-21 14:21:19 -04002643 verify(mConditionProviders, never()).setPackageOrComponentEnabled(
Julia Reynoldse1816412017-10-24 10:39:11 -04002644 anyString(), anyInt(), anyBoolean(), anyBoolean());
2645 verify(mAssistants, never()).setPackageOrComponentEnabled(
2646 any(), anyInt(), anyBoolean(), anyBoolean());
2647 }
2648
2649 @Test
2650 public void testSetListenerAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2651 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2652 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2653 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002654
2655 mBinderService.setNotificationListenerAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002656
2657 verify(mListeners, times(1)).setPackageOrComponentEnabled(
2658 c.flattenToString(), 0, true, true);
2659 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002660 c.flattenToString(), 0, false, true);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002661 verify(mAssistants, never()).setPackageOrComponentEnabled(
Julia Reynolds68263d12017-06-21 14:21:19 -04002662 any(), anyInt(), anyBoolean(), anyBoolean());
2663 }
Julia Reynolds8aebf352017-06-26 11:35:33 -04002664
2665 @Test
Julia Reynoldse1816412017-10-24 10:39:11 -04002666 public void testSetAssistantAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2667 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2668 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2669 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002670 List<UserInfo> uis = new ArrayList<>();
2671 UserInfo ui = new UserInfo();
2672 ui.id = 0;
2673 uis.add(ui);
2674 when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
2675
2676 mBinderService.setNotificationAssistantAccessGranted(c, true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002677
2678 verify(mListeners, never()).setPackageOrComponentEnabled(
2679 anyString(), anyInt(), anyBoolean(), anyBoolean());
2680 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2681 c.flattenToString(), 0, false, true);
2682 verify(mAssistants, times(1)).setPackageOrComponentEnabled(
2683 c.flattenToString(), 0, true, true);
2684 }
2685
2686 @Test
2687 public void testSetDndAccess_doesNothingOnLowRam_exceptWatch() throws Exception {
2688 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
2689 when(mActivityManager.isLowRamDevice()).thenReturn(true);
2690 ComponentName c = ComponentName.unflattenFromString("package/Component");
Julia Reynolds4afe2642019-05-01 08:42:24 -04002691
2692 mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
Julia Reynoldse1816412017-10-24 10:39:11 -04002693
2694 verify(mListeners, never()).setPackageOrComponentEnabled(
2695 anyString(), anyInt(), anyBoolean(), anyBoolean());
2696 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
2697 c.getPackageName(), 0, true, true);
2698 verify(mAssistants, never()).setPackageOrComponentEnabled(
2699 any(), anyInt(), anyBoolean(), anyBoolean());
2700 }
2701
2702 @Test
Julia Reynolds8aebf352017-06-26 11:35:33 -04002703 public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception {
2704 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002705 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002706 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002707 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002708 runnable.run();
2709 waitForIdle();
2710
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002711 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002712 }
2713
2714 @Test
2715 public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups()
2716 throws Exception {
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002717 NotificationRecord r =
2718 generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002719 mService.addNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002720
2721 r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002722 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002723 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002724 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002725 runnable.run();
2726 waitForIdle();
2727
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002728 verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002729 }
2730
2731 @Test
2732 public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
2733 throws Exception {
Julia Reynolds4db59552017-06-30 13:34:01 -04002734 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
2735 false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002736 mService.addNotification(r);
2737 mService.addEnqueuedNotification(r);
Julia Reynolds8aebf352017-06-26 11:35:33 -04002738
2739 NotificationManagerService.PostNotificationRunnable runnable =
Julia Reynolds503ed942017-10-04 16:04:56 -04002740 mService.new PostNotificationRunnable(r.getKey());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002741 runnable.run();
2742 waitForIdle();
2743
Julia Reynoldsa13b3e22017-08-10 16:58:54 -04002744 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
Julia Reynolds8aebf352017-06-26 11:35:33 -04002745 }
Beverly40239d92017-07-07 10:20:41 -04002746
Julia Reynolds4db59552017-06-30 13:34:01 -04002747 @Test
Brad Stenningd2e7a972018-10-01 09:08:42 -07002748 public void testDontAutogroupIfCritical() throws Exception {
2749 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
2750 r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
2751 mService.addEnqueuedNotification(r);
2752 NotificationManagerService.PostNotificationRunnable runnable =
2753 mService.new PostNotificationRunnable(r.getKey());
2754 runnable.run();
2755
2756 r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
2757 r.setCriticality(CriticalNotificationExtractor.CRITICAL);
2758 runnable = mService.new PostNotificationRunnable(r.getKey());
2759 mService.addEnqueuedNotification(r);
2760
2761 runnable.run();
2762 waitForIdle();
2763
2764 verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
2765 }
2766
2767 @Test
Julia Reynolds4db59552017-06-30 13:34:01 -04002768 public void testNoFakeColorizedPermission() throws Exception {
2769 when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
2770 Notification.Builder nb = new Notification.Builder(mContext,
2771 mTestNotificationChannel.getId())
2772 .setContentTitle("foo")
2773 .setColorized(true)
2774 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
2775 .setSmallIcon(android.R.drawable.sym_def_app_icon);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002776 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
2777 "testNoFakeColorizedPermission", mUid, 0,
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002778 nb.build(), new UserHandle(mUid), null, 0);
Julia Reynolds4db59552017-06-30 13:34:01 -04002779 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
2780
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002781 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Julia Reynolds4db59552017-06-30 13:34:01 -04002782 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
2783 waitForIdle();
2784
Julia Reynolds503ed942017-10-04 16:04:56 -04002785 NotificationRecord posted = mService.findNotificationLocked(
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002786 PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getUserId());
Julia Reynolds4db59552017-06-30 13:34:01 -04002787
2788 assertFalse(posted.getNotification().isColorized());
2789 }
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002790
2791 @Test
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002792 public void testGetNotificationCountLocked() {
2793 String sampleTagToExclude = null;
2794 int sampleIdToExclude = 0;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002795 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002796 NotificationRecord r =
2797 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002798 mService.addEnqueuedNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002799
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002800 }
2801 for (int i = 0; i < 20; i++) {
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002802 NotificationRecord r =
2803 generateNotificationRecord(mTestNotificationChannel, i, null, false);
Julia Reynolds503ed942017-10-04 16:04:56 -04002804 mService.addNotification(r);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002805 sampleTagToExclude = r.sbn.getTag();
2806 sampleIdToExclude = i;
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002807 }
2808
2809 // another package
2810 Notification n =
2811 new Notification.Builder(mContext, mTestNotificationChannel.getId())
2812 .setSmallIcon(android.R.drawable.sym_def_app_icon)
2813 .build();
2814
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002815 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
2816 n, new UserHandle(mUid), null, 0);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002817 NotificationRecord otherPackage =
2818 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002819 mService.addEnqueuedNotification(otherPackage);
2820 mService.addNotification(otherPackage);
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002821
2822 // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002823 // anything that's currently enqueued or posted
Geoffrey Pitsch07532c32017-07-18 11:44:06 -04002824 int userId = new UserHandle(mUid).getIdentifier();
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002825 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002826 mService.getNotificationCountLocked(PKG, userId, 0, null));
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002827 assertEquals(40,
Julia Reynolds503ed942017-10-04 16:04:56 -04002828 mService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002829
2830 // return all for package "a" - "banana" tag isn't used
Julia Reynolds8617e4e2017-09-18 16:52:37 -04002831 assertEquals(2,
Julia Reynolds503ed942017-10-04 16:04:56 -04002832 mService.getNotificationCountLocked("a", userId, 0, "banana"));
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002833
2834 // exclude a known notification - it's excluded from only the posted list, not enqueued
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002835 assertEquals(39, mService.getNotificationCountLocked(
2836 PKG, userId, sampleIdToExclude, sampleTagToExclude));
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002837 }
2838
2839 @Test
Julia Reynolds51710712017-07-19 13:48:07 -04002840 public void testAddAutogroup_requestsSort() throws Exception {
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002841 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002842 mService.addNotification(r);
2843 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002844
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002845 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04002846 }
2847
2848 @Test
2849 public void testRemoveAutogroup_requestsSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04002850 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2851 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002852 mService.addNotification(r);
2853 mService.removeAutogroupKeyLocked(r.getKey());
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002854
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002855 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds51710712017-07-19 13:48:07 -04002856 }
2857
2858 @Test
2859 public void testReaddAutogroup_noSort() throws Exception {
Julia Reynolds51710712017-07-19 13:48:07 -04002860 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
2861 r.setOverrideGroupKey("TEST");
Julia Reynolds503ed942017-10-04 16:04:56 -04002862 mService.addNotification(r);
2863 mService.addAutogroupKeyLocked(r.getKey());
Julia Reynolds51710712017-07-19 13:48:07 -04002864
Julia Reynoldsb6c83742019-07-30 18:03:40 -04002865 verify(mRankingHandler, never()).requestSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002866 }
2867
2868 @Test
2869 public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
Aaron Heuckrothe5bec152018-07-09 16:26:09 -04002870 mService.setPreferencesHelper(mPreferencesHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002871 NotificationManagerService.WorkerHandler handler = mock(
2872 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002873 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002874
2875 Map<String, Answer> answers = getSignalExtractorSideEffects();
2876 for (String message : answers.keySet()) {
Julia Reynolds503ed942017-10-04 16:04:56 -04002877 mService.clearNotifications();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002878 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002879 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002880
2881 doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
2882
Julia Reynolds503ed942017-10-04 16:04:56 -04002883 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002884 }
2885 verify(handler, times(answers.size())).scheduleSendRankingUpdate();
2886 }
2887
2888 @Test
2889 public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04002890 mService.setRankingHelper(mRankingHelper);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002891 NotificationManagerService.WorkerHandler handler = mock(
2892 NotificationManagerService.WorkerHandler.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04002893 mService.setHandler(handler);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002894
2895 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04002896 mService.addNotification(r);
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002897
Julia Reynolds503ed942017-10-04 16:04:56 -04002898 mService.handleRankingSort();
Julia Reynoldseb3dca72017-07-11 10:39:58 -04002899 verify(handler, never()).scheduleSendRankingUpdate();
Julia Reynolds6ad0aec2017-07-05 08:47:03 -04002900 }
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002901
2902 @Test
2903 public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
Julia Reynoldsd6d5a592018-04-02 11:03:32 -04002904 final String upgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002905 + "<ranking></ranking>"
2906 + "<enabled_listeners>"
2907 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2908 + "</enabled_listeners>"
2909 + "<enabled_assistants>"
2910 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2911 + "</enabled_assistants>"
2912 + "<dnd_apps>"
2913 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
2914 + "</dnd_apps>"
2915 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002916 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002917 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2918 false,
2919 UserHandle.USER_ALL);
2920 verify(mListeners, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2921 verify(mConditionProviders, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
2922 verify(mAssistants, times(1)).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002923
2924 // numbers are inflated for setup
2925 verify(mListeners, times(1)).migrateToXml();
2926 verify(mConditionProviders, times(1)).migrateToXml();
2927 verify(mAssistants, times(1)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002928 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002929 }
2930
2931 @Test
Jay Aliomer4dc508d2019-08-06 17:36:31 -04002932 public void testReadPolicyXml_readSnoozedNotificationsFromXml() throws Exception {
2933 final String upgradeXml = "<notification-policy version=\"1\">"
2934 + "<snoozed-notifications>></snoozed-notifications>"
2935 + "</notification-policy>";
2936 mService.readPolicyXml(
2937 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
2938 false,
2939 UserHandle.USER_ALL);
2940 verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class));
2941 }
2942
2943 @Test
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002944 public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
2945 final String preupgradeXml = "<notification-policy version=\"1\">"
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002946 + "<ranking></ranking>"
2947 + "</notification-policy>";
Julia Reynolds503ed942017-10-04 16:04:56 -04002948 mService.readPolicyXml(
Annie Meng8b646fd2019-02-01 18:46:42 +00002949 new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
2950 false,
2951 UserHandle.USER_ALL);
2952 verify(mListeners, never()).readXml(any(), any(), anyBoolean(), anyInt());
2953 verify(mConditionProviders, never()).readXml(any(), any(), anyBoolean(), anyInt());
2954 verify(mAssistants, never()).readXml(any(), any(), anyBoolean(), anyInt());
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002955
2956 // numbers are inflated for setup
2957 verify(mListeners, times(2)).migrateToXml();
2958 verify(mConditionProviders, times(2)).migrateToXml();
2959 verify(mAssistants, times(2)).migrateToXml();
Tony Mak9a3c1f12019-03-04 16:04:42 +00002960 verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -04002961 }
2962
Annie Meng8b646fd2019-02-01 18:46:42 +00002963 @Test
2964 public void testReadPolicyXml_doesNotRestoreManagedServicesForManagedUser() throws Exception {
2965 final String policyXml = "<notification-policy version=\"1\">"
2966 + "<ranking></ranking>"
2967 + "<enabled_listeners>"
2968 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2969 + "</enabled_listeners>"
2970 + "<enabled_assistants>"
2971 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2972 + "</enabled_assistants>"
2973 + "<dnd_apps>"
2974 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2975 + "</dnd_apps>"
2976 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04002977 when(mUm.isManagedProfile(10)).thenReturn(true);
Annie Meng8b646fd2019-02-01 18:46:42 +00002978 mService.readPolicyXml(
2979 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
2980 true,
2981 10);
2982 verify(mListeners, never()).readXml(any(), any(), eq(true), eq(10));
2983 verify(mConditionProviders, never()).readXml(any(), any(), eq(true), eq(10));
2984 verify(mAssistants, never()).readXml(any(), any(), eq(true), eq(10));
2985 }
2986
2987 @Test
2988 public void testReadPolicyXml_restoresManagedServicesForNonManagedUser() throws Exception {
2989 final String policyXml = "<notification-policy version=\"1\">"
2990 + "<ranking></ranking>"
2991 + "<enabled_listeners>"
2992 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2993 + "</enabled_listeners>"
2994 + "<enabled_assistants>"
2995 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2996 + "</enabled_assistants>"
2997 + "<dnd_apps>"
2998 + "<service_listing approved=\"test\" user=\"10\" primary=\"true\" />"
2999 + "</dnd_apps>"
3000 + "</notification-policy>";
Julia Reynolds0c245002019-03-27 16:10:11 -04003001 when(mUm.isManagedProfile(10)).thenReturn(false);
Annie Meng8b646fd2019-02-01 18:46:42 +00003002 mService.readPolicyXml(
3003 new BufferedInputStream(new ByteArrayInputStream(policyXml.getBytes())),
3004 true,
3005 10);
3006 verify(mListeners, times(1)).readXml(any(), any(), eq(true), eq(10));
3007 verify(mConditionProviders, times(1)).readXml(any(), any(), eq(true), eq(10));
3008 verify(mAssistants, times(1)).readXml(any(), any(), eq(true), eq(10));
3009 }
Beverlyd4f96492017-08-02 13:36:11 -04003010
3011 @Test
3012 public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
3013 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
Julia Reynolds503ed942017-10-04 16:04:56 -04003014 mService.mZenModeHelper = mZenModeHelper;
3015 mService.mLocaleChangeReceiver.onReceive(mContext,
Beverlyd4f96492017-08-02 13:36:11 -04003016 new Intent(Intent.ACTION_LOCALE_CHANGED));
3017
3018 verify(mZenModeHelper, times(1)).updateDefaultZenRules();
3019 }
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003020
3021 @Test
3022 public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003023 String preOPkg = PKG_N_MR1;
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003024 final ApplicationInfo legacy = new ApplicationInfo();
3025 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
3026 when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
3027 .thenReturn(legacy);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003028 when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
3029 .thenReturn(Binder.getCallingUid());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003030 getContext().setMockPackageManager(mPackageManagerClient);
3031
3032 Notification.Builder nb = new Notification.Builder(mContext,
3033 NotificationChannel.DEFAULT_CHANNEL_ID)
3034 .setContentTitle("foo")
3035 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003036 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003037 .setPriority(Notification.PRIORITY_MIN);
3038
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003039 StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3040 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003041 Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003042
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003043 mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
3044 sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003045 waitForIdle();
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003046
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003047 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003048 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003049
3050 nb = new Notification.Builder(mContext)
3051 .setContentTitle("foo")
3052 .setSmallIcon(android.R.drawable.sym_def_app_icon)
Julia Reynoldse5c60452018-04-30 14:41:36 -04003053 .setFlag(FLAG_FOREGROUND_SERVICE, true)
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003054 .setPriority(Notification.PRIORITY_MIN);
3055
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003056 sbn = new StatusBarNotification(preOPkg, preOPkg, 9,
3057 "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(),
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04003058 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003059
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003060 mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg,
3061 "testBumpFGImportance_noChannelChangePreOApp",
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003062 sbn.getId(), sbn.getNotification(), sbn.getUserId());
3063 waitForIdle();
3064 assertEquals(IMPORTANCE_LOW,
Julia Reynolds503ed942017-10-04 16:04:56 -04003065 mService.getNotificationRecord(sbn.getKey()).getImportance());
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003066
3067 NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04003068 preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
Julia Reynolds8617e4e2017-09-18 16:52:37 -04003069 assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
3070 }
Julia Reynolds503ed942017-10-04 16:04:56 -04003071
3072 @Test
3073 public void testStats_updatedOnDirectReply() throws Exception {
3074 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3075 mService.addNotification(r);
3076
3077 mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey());
3078 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied());
Tony Makeda84a72018-11-19 17:01:32 +00003079 verify(mAssistants).notifyAssistantNotificationDirectReplyLocked(eq(r.sbn));
Julia Reynolds503ed942017-10-04 16:04:56 -04003080 }
3081
3082 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003083 public void testStats_updatedOnUserExpansion() throws Exception {
3084 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds503ed942017-10-04 16:04:56 -04003085 mService.addNotification(r);
3086
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003087 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
3088 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00003089 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003090 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003091
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003092 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
3093 NOTIFICATION_LOCATION_UNKNOWN);
Tony Makeda84a72018-11-19 17:01:32 +00003094 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
Julia Reynolds503ed942017-10-04 16:04:56 -04003095 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
3096 }
3097
3098 @Test
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003099 public void testStats_notUpdatedOnAutoExpansion() throws Exception {
3100 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3101 mService.addNotification(r);
3102
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003103 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
3104 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003105 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003106 verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
3107
Gustav Senntona8e38aa2019-01-22 14:55:39 +00003108 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
3109 NOTIFICATION_LOCATION_UNKNOWN);
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003110 assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
Tony Makeda84a72018-11-19 17:01:32 +00003111 verify(mAssistants).notifyAssistantExpansionChangedLocked(
3112 eq(r.sbn), eq(false), eq((false)));
Julia Reynolds84dc96b2017-11-14 09:51:01 -05003113 }
3114
3115 @Test
Julia Reynolds503ed942017-10-04 16:04:56 -04003116 public void testStats_updatedOnViewSettings() throws Exception {
3117 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3118 mService.addNotification(r);
3119
3120 mService.mNotificationDelegate.onNotificationSettingsViewed(r.getKey());
3121 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasViewedSettings());
3122 }
3123
3124 @Test
3125 public void testStats_updatedOnVisibilityChanged() throws Exception {
3126 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3127 mService.addNotification(r);
3128
Dieter Hsud39f0d52018-04-14 02:08:30 +08003129 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 1, 2, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003130 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3131 new NotificationVisibility[] {nv}, new NotificationVisibility[]{});
3132 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3133 mService.mNotificationDelegate.onNotificationVisibilityChanged(
3134 new NotificationVisibility[] {}, new NotificationVisibility[]{nv});
3135 assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasSeen());
3136 }
3137
3138 @Test
3139 public void testStats_dismissalSurface() throws Exception {
3140 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3141 mService.addNotification(r);
3142
Dieter Hsud39f0d52018-04-14 02:08:30 +08003143 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
Julia Reynolds503ed942017-10-04 16:04:56 -04003144 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003145 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3146 NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
Julia Reynolds503ed942017-10-04 16:04:56 -04003147 waitForIdle();
3148
3149 assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
3150 }
3151
3152 @Test
Julia Reynoldsfd4099d2018-08-21 11:06:06 -04003153 public void testStats_dismissalSentiment() throws Exception {
3154 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3155 mService.addNotification(r);
3156
3157 final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
3158 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
3159 r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
3160 NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
3161 waitForIdle();
3162
3163 assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
3164 r.getStats().getDismissalSentiment());
3165 }
3166
3167 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003168 public void testApplyAdjustmentMultiUser() throws Exception {
Julia Reynolds503ed942017-10-04 16:04:56 -04003169 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3170 mService.addNotification(r);
3171 NotificationManagerService.WorkerHandler handler = mock(
3172 NotificationManagerService.WorkerHandler.class);
3173 mService.setHandler(handler);
3174
Julia Reynolds70aaea72018-07-13 13:38:34 -04003175 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3176
Julia Reynolds503ed942017-10-04 16:04:56 -04003177 Bundle signals = new Bundle();
3178 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003179 USER_SENTIMENT_NEGATIVE);
3180 Adjustment adjustment = new Adjustment(
3181 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3182 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3183
3184 waitForIdle();
3185
3186 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3187 }
3188
3189 @Test
Julia Reynolds27c0a962018-12-10 12:37:28 -05003190 public void testAssistantBlockingTriggersCancel() throws Exception {
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003191 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3192 mService.addNotification(r);
3193 NotificationManagerService.WorkerHandler handler = mock(
3194 NotificationManagerService.WorkerHandler.class);
3195 mService.setHandler(handler);
3196
3197 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003198 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Julia Reynoldsefcdff42018-08-09 09:42:56 -04003199 Adjustment adjustment = new Adjustment(
3200 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3201 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
3202 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3203
3204 waitForIdle();
3205
3206 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3207 verify(handler, times(1)).scheduleCancelNotification(any());
3208 }
3209
3210 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003211 public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
3212 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3213 mService.addEnqueuedNotification(r);
3214 NotificationManagerService.WorkerHandler handler = mock(
3215 NotificationManagerService.WorkerHandler.class);
3216 mService.setHandler(handler);
3217 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3218
3219 Bundle signals = new Bundle();
3220 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3221 USER_SENTIMENT_NEGATIVE);
3222 Adjustment adjustment = new Adjustment(
3223 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3224 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3225
3226 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
3227 }
3228
3229 @Test
Julia Reynoldsdc6adc62019-04-08 10:35:40 -04003230 public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
Julia Reynolds27c0a962018-12-10 12:37:28 -05003231 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3232 mService.addEnqueuedNotification(r);
3233 NotificationManagerService.WorkerHandler handler = mock(
3234 NotificationManagerService.WorkerHandler.class);
3235 mService.setHandler(handler);
3236 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3237
3238 Bundle signals = new Bundle();
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04003239 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Julia Reynolds27c0a962018-12-10 12:37:28 -05003240 Adjustment adjustment = new Adjustment(
3241 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3242 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3243
3244 assertEquals(IMPORTANCE_LOW, r.getImportance());
3245 }
3246
3247 @Test
Julia Reynolds70aaea72018-07-13 13:38:34 -04003248 public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
3249 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3250 mService.addEnqueuedNotification(r);
3251 NotificationManagerService.WorkerHandler handler = mock(
3252 NotificationManagerService.WorkerHandler.class);
3253 mService.setHandler(handler);
3254 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
3255
3256 Bundle signals = new Bundle();
3257 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3258 USER_SENTIMENT_NEGATIVE);
3259 Adjustment adjustment = new Adjustment(
3260 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3261 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3262
3263 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
3264
3265 waitForIdle();
3266
3267 verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
3268 }
3269
3270 @Test
3271 public void testUserSentimentChangeTriggersUpdate() throws Exception {
3272 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3273 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003274 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
3275
3276 Bundle signals = new Bundle();
3277 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
3278 USER_SENTIMENT_NEGATIVE);
Julia Reynolds503ed942017-10-04 16:04:56 -04003279 Adjustment adjustment = new Adjustment(
3280 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3281 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
3282
3283 waitForIdle();
3284
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003285 verify(mRankingHandler, timeout(300).times(1)).requestSort();
Julia Reynolds503ed942017-10-04 16:04:56 -04003286 }
Julia Reynolds7bcb57b2018-01-22 10:37:58 -05003287
3288 @Test
Julia Reynolds666ccf02018-06-18 10:19:20 -04003289 public void testTooLateAdjustmentTriggersUpdate() throws Exception {
3290 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3291 mService.addNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003292 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003293
3294 Bundle signals = new Bundle();
3295 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003296 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003297 Adjustment adjustment = new Adjustment(
3298 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3299 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3300
3301 waitForIdle();
3302
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003303 verify(mRankingHandler, times(1)).requestSort();
Julia Reynolds666ccf02018-06-18 10:19:20 -04003304 }
3305
3306 @Test
3307 public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
3308 final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
3309 mService.addEnqueuedNotification(r);
Julia Reynolds70aaea72018-07-13 13:38:34 -04003310 when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003311
3312 Bundle signals = new Bundle();
3313 signals.putInt(Adjustment.KEY_USER_SENTIMENT,
Julia Reynolds70aaea72018-07-13 13:38:34 -04003314 USER_SENTIMENT_NEGATIVE);
Julia Reynolds666ccf02018-06-18 10:19:20 -04003315 Adjustment adjustment = new Adjustment(
3316 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
3317 mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
3318
Julia Reynoldsb6c83742019-07-30 18:03:40 -04003319 assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
Julia Reynolds666ccf02018-06-18 10:19:20 -04003320 }
3321
3322 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003323 public void testRestore() throws Exception {
3324 int systemChecks = mService.countSystemChecks;
Julia Reynolds57a974b2019-10-07 11:51:47 -04003325 mBinderService.applyRestore(null, USER_SYSTEM);
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003326 assertEquals(1, mService.countSystemChecks - systemChecks);
3327 }
3328
3329 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003330 public void testBackupEmptySound() throws Exception {
3331 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3332 channel.setSound(Uri.EMPTY, null);
3333
3334 XmlSerializer serializer = new FastXmlSerializer();
3335 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3336 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3337 channel.writeXmlForBackup(serializer, getContext());
3338
3339 XmlPullParser parser = Xml.newPullParser();
3340 parser.setInput(new BufferedInputStream(
3341 new ByteArrayInputStream(baos.toByteArray())), null);
3342 NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3343 restored.populateFromXmlForRestore(parser, getContext());
3344
3345 assertNull(restored.getSound());
3346 }
3347
3348 @Test
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003349 public void testBackup() throws Exception {
3350 int systemChecks = mService.countSystemChecks;
Jay Aliomer4204f252019-08-26 11:36:53 -04003351 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
3352 .thenReturn(new ArraySet<>());
Julia Reynoldsd78263d2018-01-30 10:40:41 -05003353 mBinderService.getBackupPayload(1);
3354 assertEquals(1, mService.countSystemChecks - systemChecks);
3355 }
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003356
3357 @Test
Julia Reynolds469144c2019-06-21 14:30:28 -04003358 public void testEmptyVibration_noException() throws Exception {
3359 NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
3360 channel.setVibrationPattern(new long[0]);
3361
3362 XmlSerializer serializer = new FastXmlSerializer();
3363 ByteArrayOutputStream baos = new ByteArrayOutputStream();
3364 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
3365 channel.writeXml(serializer);
3366 }
3367
3368 @Test
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003369 public void updateUriPermissions_update() throws Exception {
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003370 NotificationChannel c = new NotificationChannel(
Julia Reynolds27c0a962018-12-10 12:37:28 -05003371 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003372 c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
3373 Message message1 = new Message("", 0, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003374 message1.setData("",
3375 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003376 Message message2 = new Message("", 1, "");
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003377 message2.setData("",
3378 ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2));
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003379
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003380 Notification.Builder nbA = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003381 .setContentTitle("foo")
3382 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3383 .setStyle(new Notification.MessagingStyle("")
3384 .addMessage(message1)
3385 .addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003386 NotificationRecord recordA = new NotificationRecord(mContext, new StatusBarNotification(
3387 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003388
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003389 // First post means we grant access to both
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003390 reset(mUgm);
3391 reset(mUgmInternal);
3392 when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003393 mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003394 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003395 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003396 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003397 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003398 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
3399
3400 Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003401 .setContentTitle("foo")
3402 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3403 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003404 NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(PKG,
3405 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003406
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003407 // Update means we drop access to first
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003408 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003409 mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003410 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003411 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
3412 eq(message1.getDataUri()), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003413
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003414 // Update back means we grant access to first again
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003415 reset(mUgm);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003416 mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003417 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003418 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003419 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003420
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003421 // And update to empty means we drop everything
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003422 reset(mUgmInternal);
Jeff Sharkey6a97cc32018-04-17 12:16:20 -06003423 mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
Julia Reynolds57a974b2019-10-07 11:51:47 -04003424 USER_SYSTEM);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07003425 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
Julia Reynoldse0d711f2017-09-01 08:50:47 -04003426 anyInt(), anyInt());
3427 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003428
3429 @Test
Robin Leed107af62018-04-27 13:55:56 +02003430 public void testVisitUris() throws Exception {
3431 final Uri audioContents = Uri.parse("content://com.example/audio");
3432 final Uri backgroundImage = Uri.parse("content://com.example/background");
3433
3434 Bundle extras = new Bundle();
3435 extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
3436 extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
3437
3438 Notification n = new Notification.Builder(mContext, "a")
3439 .setContentTitle("notification with uris")
3440 .setSmallIcon(android.R.drawable.sym_def_app_icon)
3441 .addExtras(extras)
3442 .build();
3443
3444 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
3445 n.visitUris(visitor);
3446 verify(visitor, times(1)).accept(eq(audioContents));
3447 verify(visitor, times(1)).accept(eq(backgroundImage));
3448 }
3449
3450 @Test
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003451 public void testSetNotificationPolicy_preP_setOldFields() {
3452 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3453 mService.mZenModeHelper = mZenModeHelper;
3454 NotificationManager.Policy userPolicy =
3455 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3456 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3457
3458 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3459 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3460
3461 int expected = SUPPRESSED_EFFECT_BADGE
3462 | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
Julia Reynoldseac2da22018-04-12 10:48:46 -04003463 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
3464 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
Julia Reynoldsccc6ae62018-03-01 16:24:49 -05003465 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3466
3467 assertEquals(expected, actual);
3468 }
3469
3470 @Test
3471 public void testSetNotificationPolicy_preP_setNewFields() {
3472 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3473 mService.mZenModeHelper = mZenModeHelper;
3474 NotificationManager.Policy userPolicy =
3475 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3476 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3477
3478 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3479 SUPPRESSED_EFFECT_NOTIFICATION_LIST);
3480
3481 int expected = SUPPRESSED_EFFECT_BADGE;
3482 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3483
3484 assertEquals(expected, actual);
3485 }
3486
3487 @Test
3488 public void testSetNotificationPolicy_preP_setOldNewFields() {
3489 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3490 mService.mZenModeHelper = mZenModeHelper;
3491 NotificationManager.Policy userPolicy =
3492 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3493 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3494
3495 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3496 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3497
3498 int expected =
3499 SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
3500 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
3501
3502 assertEquals(expected, actual);
3503 }
3504
3505 @Test
3506 public void testSetNotificationPolicy_P_setOldFields() {
3507 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3508 mService.mZenModeHelper = mZenModeHelper;
3509 NotificationManager.Policy userPolicy =
3510 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3511 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3512
3513 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3514 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
3515
3516 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
3517 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
3518 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3519 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3520
3521 assertEquals(expected, actual);
3522 }
3523
3524 @Test
3525 public void testSetNotificationPolicy_P_setNewFields() {
3526 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3527 mService.mZenModeHelper = mZenModeHelper;
3528 NotificationManager.Policy userPolicy =
3529 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3530 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3531
3532 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3533 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
3534 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3535
3536 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
3537 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
3538 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3539 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3540
3541 assertEquals(expected, actual);
3542 }
3543
3544 @Test
3545 public void testSetNotificationPolicy_P_setOldNewFields() {
3546 ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
3547 mService.mZenModeHelper = mZenModeHelper;
3548 NotificationManager.Policy userPolicy =
3549 new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
3550 when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
3551
3552 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
3553 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
3554
3555 int expected = SUPPRESSED_EFFECT_STATUS_BAR;
3556 int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3557
3558 assertEquals(expected, actual);
3559
3560 appPolicy = new NotificationManager.Policy(0, 0, 0,
3561 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
3562 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
3563
3564 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
3565 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
3566 actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
3567
3568 assertEquals(expected, actual);
3569 }
Julia Reynolds7217dc92018-03-07 12:12:09 -05003570
3571 @Test
Julia Reynoldse5c60452018-04-30 14:41:36 -04003572 public void testVisualDifference_foreground() {
3573 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3574 .setContentTitle("foo");
3575 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3576 nb1.build(), new UserHandle(mUid), null, 0);
3577 NotificationRecord r1 =
3578 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3579
3580 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3581 .setFlag(FLAG_FOREGROUND_SERVICE, true)
3582 .setContentTitle("bar");
3583 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3584 nb2.build(), new UserHandle(mUid), null, 0);
3585 NotificationRecord r2 =
3586 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3587
3588 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3589 }
3590
3591 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003592 public void testVisualDifference_diffTitle() {
3593 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3594 .setContentTitle("foo");
3595 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3596 nb1.build(), new UserHandle(mUid), null, 0);
3597 NotificationRecord r1 =
3598 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3599
3600 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3601 .setContentTitle("bar");
3602 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3603 nb2.build(), new UserHandle(mUid), null, 0);
3604 NotificationRecord r2 =
3605 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3606
3607 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3608 }
3609
3610 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003611 public void testVisualDifference_inboxStyle() {
3612 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3613 .setStyle(new Notification.InboxStyle()
3614 .addLine("line1").addLine("line2"));
3615 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3616 nb1.build(), new UserHandle(mUid), null, 0);
3617 NotificationRecord r1 =
3618 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3619
3620 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3621 .setStyle(new Notification.InboxStyle()
3622 .addLine("line1").addLine("line2_changed"));
3623 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3624 nb2.build(), new UserHandle(mUid), null, 0);
3625 NotificationRecord r2 =
3626 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3627
3628 assertTrue(mService.isVisuallyInterruptive(r1, r2)); // line 2 changed unnoticed
3629
3630 Notification.Builder nb3 = new Notification.Builder(mContext, "")
3631 .setStyle(new Notification.InboxStyle()
3632 .addLine("line1"));
3633 StatusBarNotification sbn3 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3634 nb3.build(), new UserHandle(mUid), null, 0);
3635 NotificationRecord r3 =
3636 new NotificationRecord(mContext, sbn3, mock(NotificationChannel.class));
3637
3638 assertTrue(mService.isVisuallyInterruptive(r1, r3)); // line 2 removed unnoticed
3639
3640 Notification.Builder nb4 = new Notification.Builder(mContext, "")
3641 .setStyle(new Notification.InboxStyle()
3642 .addLine("line1").addLine("line2").addLine("line3"));
3643 StatusBarNotification sbn4 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3644 nb4.build(), new UserHandle(mUid), null, 0);
3645 NotificationRecord r4 =
3646 new NotificationRecord(mContext, sbn4, mock(NotificationChannel.class));
3647
3648 assertTrue(mService.isVisuallyInterruptive(r1, r4)); // line 3 added unnoticed
3649
3650 Notification.Builder nb5 = new Notification.Builder(mContext, "")
3651 .setContentText("not an inbox");
3652 StatusBarNotification sbn5 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3653 nb5.build(), new UserHandle(mUid), null, 0);
3654 NotificationRecord r5 =
3655 new NotificationRecord(mContext, sbn5, mock(NotificationChannel.class));
3656
3657 assertTrue(mService.isVisuallyInterruptive(r1, r5)); // changed Styles, went unnoticed
3658 }
3659
3660 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003661 public void testVisualDifference_diffText() {
3662 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3663 .setContentText("foo");
3664 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3665 nb1.build(), new UserHandle(mUid), null, 0);
3666 NotificationRecord r1 =
3667 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3668
3669 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3670 .setContentText("bar");
3671 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3672 nb2.build(), new UserHandle(mUid), null, 0);
3673 NotificationRecord r2 =
3674 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3675
3676 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3677 }
3678
3679 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003680 public void testVisualDifference_sameText() {
3681 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3682 .setContentText("foo");
3683 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3684 nb1.build(), new UserHandle(mUid), null, 0);
3685 NotificationRecord r1 =
3686 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3687
3688 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3689 .setContentText("foo");
3690 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3691 nb2.build(), new UserHandle(mUid), null, 0);
3692 NotificationRecord r2 =
3693 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3694
3695 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3696 }
3697
3698 @Test
3699 public void testVisualDifference_sameTextButStyled() {
3700 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3701 .setContentText(Html.fromHtml("<b>foo</b>"));
3702 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3703 nb1.build(), new UserHandle(mUid), null, 0);
3704 NotificationRecord r1 =
3705 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3706
3707 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3708 .setContentText(Html.fromHtml("<b>foo</b>"));
3709 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3710 nb2.build(), new UserHandle(mUid), null, 0);
3711 NotificationRecord r2 =
3712 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3713
3714 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3715 }
3716
3717 @Test
3718 public void testVisualDifference_diffTextButStyled() {
3719 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3720 .setContentText(Html.fromHtml("<b>foo</b>"));
3721 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3722 nb1.build(), new UserHandle(mUid), null, 0);
3723 NotificationRecord r1 =
3724 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3725
3726 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3727 .setContentText(Html.fromHtml("<b>bar</b>"));
3728 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3729 nb2.build(), new UserHandle(mUid), null, 0);
3730 NotificationRecord r2 =
3731 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3732
3733 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3734 }
3735
3736 @Test
Julia Reynolds7217dc92018-03-07 12:12:09 -05003737 public void testVisualDifference_diffProgress() {
3738 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3739 .setProgress(100, 90, false);
3740 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3741 nb1.build(), new UserHandle(mUid), null, 0);
3742 NotificationRecord r1 =
3743 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3744
3745 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3746 .setProgress(100, 100, false);
3747 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3748 nb2.build(), new UserHandle(mUid), null, 0);
3749 NotificationRecord r2 =
3750 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3751
3752 assertTrue(mService.isVisuallyInterruptive(r1, r2));
3753 }
3754
3755 @Test
3756 public void testVisualDifference_diffProgressNotDone() {
3757 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3758 .setProgress(100, 90, false);
3759 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3760 nb1.build(), new UserHandle(mUid), null, 0);
3761 NotificationRecord r1 =
3762 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3763
3764 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3765 .setProgress(100, 91, false);
3766 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3767 nb2.build(), new UserHandle(mUid), null, 0);
3768 NotificationRecord r2 =
3769 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3770
3771 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3772 }
Beverly5a20a5e2018-03-06 15:02:44 -05003773
3774 @Test
Dan Sandler7d67bd42018-05-15 14:06:38 -04003775 public void testVisualDifference_sameProgressStillDone() {
3776 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3777 .setProgress(100, 100, false);
3778 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3779 nb1.build(), new UserHandle(mUid), null, 0);
3780 NotificationRecord r1 =
3781 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3782
3783 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3784 .setProgress(100, 100, false);
3785 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3786 nb2.build(), new UserHandle(mUid), null, 0);
3787 NotificationRecord r2 =
3788 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3789
3790 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3791 }
3792
3793 @Test
Julia Reynoldsa4fb9da2018-06-04 12:27:58 -04003794 public void testVisualDifference_summary() {
3795 Notification.Builder nb1 = new Notification.Builder(mContext, "")
3796 .setGroup("bananas")
3797 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3798 .setContentText("foo");
3799 StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3800 nb1.build(), new UserHandle(mUid), null, 0);
3801 NotificationRecord r1 =
3802 new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
3803
3804 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3805 .setGroup("bananas")
3806 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3807 .setContentText("bar");
3808 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3809 nb2.build(), new UserHandle(mUid), null, 0);
3810 NotificationRecord r2 =
3811 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3812
3813 assertFalse(mService.isVisuallyInterruptive(r1, r2));
3814 }
3815
3816 @Test
Julia Reynolds760fa762018-06-19 15:39:23 -04003817 public void testVisualDifference_summaryNewNotification() {
3818 Notification.Builder nb2 = new Notification.Builder(mContext, "")
3819 .setGroup("bananas")
3820 .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
3821 .setContentText("bar");
3822 StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
3823 nb2.build(), new UserHandle(mUid), null, 0);
3824 NotificationRecord r2 =
3825 new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
3826
3827 assertFalse(mService.isVisuallyInterruptive(null, r2));
3828 }
3829
3830 @Test
Beverly5a20a5e2018-03-06 15:02:44 -05003831 public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
3832 // post 2 notification from this package
3833 final NotificationRecord notif1 = generateNotificationRecord(
3834 mTestNotificationChannel, 1, null, true);
3835 final NotificationRecord notif2 = generateNotificationRecord(
3836 mTestNotificationChannel, 2, null, false);
3837 mService.addNotification(notif1);
3838 mService.addNotification(notif2);
3839
3840 // on broadcast, hide the 2 notifications
3841 mService.simulatePackageSuspendBroadcast(true, PKG);
3842 ArgumentCaptor<List> captorHide = ArgumentCaptor.forClass(List.class);
3843 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3844 assertEquals(2, captorHide.getValue().size());
3845
3846 // on broadcast, unhide the 2 notifications
3847 mService.simulatePackageSuspendBroadcast(false, PKG);
3848 ArgumentCaptor<List> captorUnhide = ArgumentCaptor.forClass(List.class);
3849 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3850 assertEquals(2, captorUnhide.getValue().size());
3851 }
3852
3853 @Test
3854 public void testNoNotificationsHiddenOnSuspendedPackageBroadcast() {
3855 // post 2 notification from this package
3856 final NotificationRecord notif1 = generateNotificationRecord(
3857 mTestNotificationChannel, 1, null, true);
3858 final NotificationRecord notif2 = generateNotificationRecord(
3859 mTestNotificationChannel, 2, null, false);
3860 mService.addNotification(notif1);
3861 mService.addNotification(notif2);
3862
3863 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3864 mService.simulatePackageSuspendBroadcast(true, "test_package");
3865 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3866 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3867 assertEquals(0, captor.getValue().size());
3868 }
Kristian Monsen05f34792018-04-09 10:27:16 +02003869
3870 @Test
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003871 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast() {
3872 // Post 2 notifications from 2 packages
3873 NotificationRecord pkgA = new NotificationRecord(mContext,
3874 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3875 mService.addNotification(pkgA);
3876 NotificationRecord pkgB = new NotificationRecord(mContext,
3877 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3878 mService.addNotification(pkgB);
3879
3880 // on broadcast, hide one of the packages
3881 mService.simulatePackageDistractionBroadcast(
3882 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a"});
3883 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
3884 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
3885 assertEquals(1, captorHide.getValue().size());
3886 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3887
3888 // on broadcast, unhide the package
3889 mService.simulatePackageDistractionBroadcast(
3890 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a"});
3891 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
3892 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
3893 assertEquals(1, captorUnhide.getValue().size());
3894 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3895 }
3896
3897 @Test
3898 public void testHideAndUnhideNotificationsOnDistractingPackageBroadcast_multiPkg() {
3899 // Post 2 notifications from 2 packages
3900 NotificationRecord pkgA = new NotificationRecord(mContext,
3901 generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
3902 mService.addNotification(pkgA);
3903 NotificationRecord pkgB = new NotificationRecord(mContext,
3904 generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
3905 mService.addNotification(pkgB);
3906
3907 // on broadcast, hide one of the packages
3908 mService.simulatePackageDistractionBroadcast(
3909 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
3910 ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003911
3912 // should be called only once.
3913 verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003914 assertEquals(2, captorHide.getValue().size());
3915 assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
3916 assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
3917
3918 // on broadcast, unhide the package
3919 mService.simulatePackageDistractionBroadcast(
3920 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
3921 ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
woongki minbbc97282019-09-25 11:50:48 +09003922
3923 // should be called only once.
3924 verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
Julia Reynolds0e5a3432019-01-17 09:40:46 -05003925 assertEquals(2, captorUnhide.getValue().size());
3926 assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
3927 assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
3928 }
3929
3930 @Test
3931 public void testNoNotificationsHiddenOnDistractingPackageBroadcast() {
3932 // post notification from this package
3933 final NotificationRecord notif1 = generateNotificationRecord(
3934 mTestNotificationChannel, 1, null, true);
3935 mService.addNotification(notif1);
3936
3937 // on broadcast, nothing is hidden since no notifications are of package "test_package"
3938 mService.simulatePackageDistractionBroadcast(
3939 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"test_package"});
3940 ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
3941 verify(mListeners, times(1)).notifyHiddenLocked(captor.capture());
3942 assertEquals(0, captor.getValue().size());
3943 }
3944
3945 @Test
Kristian Monsen05f34792018-04-09 10:27:16 +02003946 public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
3947 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3948 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3949 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3950 .thenReturn(new String[] {"a", "b", "c"});
3951 when(mContext.getResources()).thenReturn(mResources);
3952
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003953 assertEquals(false, mService.canUseManagedServices(null, 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003954 }
3955
3956 @Test
3957 public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
3958 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3959 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3960 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3961 .thenReturn(new String[] {"a", "b", "c"});
3962 when(mContext.getResources()).thenReturn(mResources);
3963
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003964 assertEquals(true, mService.canUseManagedServices("b", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003965 }
3966
3967 @Test
3968 public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
3969 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3970 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3971 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3972 .thenReturn(new String[] {"a", "b", "c"});
3973 when(mContext.getResources()).thenReturn(mResources);
3974
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003975 assertEquals(false, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003976 }
3977
3978 @Test
3979 public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
3980 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
3981 when(mActivityManager.isLowRamDevice()).thenReturn(true);
3982 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3983 .thenReturn(new String[] {"a", "b", "c"});
3984 when(mContext.getResources()).thenReturn(mResources);
3985
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003986 assertEquals(true, mService.canUseManagedServices("d", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003987 }
3988
3989 @Test
3990 public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
3991 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
3992 when(mActivityManager.isLowRamDevice()).thenReturn(false);
3993 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
3994 .thenReturn(new String[] {"a", "b", "c"});
3995 when(mContext.getResources()).thenReturn(mResources);
3996
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05003997 assertEquals(true, mService.canUseManagedServices("d", 0 , null));
Kristian Monsen05f34792018-04-09 10:27:16 +02003998 }
3999
4000 @Test
4001 public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
4002 when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
4003 when(mActivityManager.isLowRamDevice()).thenReturn(false);
4004 when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
4005 .thenReturn(new String[] {"a", "b", "c"});
4006 when(mContext.getResources()).thenReturn(mResources);
4007
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -05004008 assertEquals(true, mService.canUseManagedServices("d", 0, null));
4009 }
4010
4011 @Test
4012 public void testCanUseManagedServices_hasPermission() throws Exception {
4013 when(mPackageManager.checkPermission("perm", "pkg", 0))
4014 .thenReturn(PackageManager.PERMISSION_GRANTED);
4015
4016 assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
4017 }
4018
4019 @Test
4020 public void testCanUseManagedServices_noPermission() throws Exception {
4021 when(mPackageManager.checkPermission("perm", "pkg", 0))
4022 .thenReturn(PackageManager.PERMISSION_DENIED);
4023
4024 assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
4025 }
4026
4027 @Test
4028 public void testCanUseManagedServices_permDoesNotMatter() {
4029 assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
Kristian Monsen05f34792018-04-09 10:27:16 +02004030 }
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004031
4032 @Test
4033 public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
4034 final NotificationRecord r = generateNotificationRecord(
4035 mTestNotificationChannel, 1, null, true);
4036 r.setTextChanged(true);
4037 mService.addNotification(r);
4038
4039 mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
4040 {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
4041 new NotificationVisibility[]{});
4042
4043 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4044 }
4045
4046 @Test
4047 public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
4048 throws RemoteException {
4049 final NotificationRecord r = generateNotificationRecord(
4050 mTestNotificationChannel, 1, null, true);
4051 r.setTextChanged(true);
4052 mService.addNotification(r);
4053
4054 mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
4055
4056 verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
4057 }
4058
4059 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004060 public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
Julia Reynoldsb3c68ff2018-05-22 14:58:39 -04004061 throws RemoteException {
4062 final NotificationRecord r = generateNotificationRecord(
4063 mTestNotificationChannel, 1, null, true);
4064 r.setInterruptive(true);
4065 mService.addNotification(r);
4066
4067 mService.maybeRecordInterruptionLocked(r);
4068 mService.maybeRecordInterruptionLocked(r);
4069
4070 verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
4071 anyString(), anyString(), anyInt());
4072 }
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004073
4074 @Test
Mady Mellorc39b4ae2019-01-09 17:11:37 -08004075 public void testBubble() throws Exception {
4076 mBinderService.setBubblesAllowed(PKG, mUid, false);
4077 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
Julia Reynolds33ab8a02018-12-17 16:19:52 -05004078 }
4079
4080 @Test
Mady Mellor9db685a2019-01-23 13:23:37 -08004081 public void testUserApprovedBubblesForPackage() throws Exception {
4082 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4083 mBinderService.setBubblesAllowed(PKG, mUid, true);
4084 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4085 assertTrue(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
4086 }
4087
4088 @Test
4089 public void testUserRejectsBubblesForPackage() throws Exception {
4090 assertFalse(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4091 mBinderService.setBubblesAllowed(PKG, mUid, false);
4092 assertTrue(mBinderService.hasUserApprovedBubblesForPackage(PKG, mUid));
4093 assertFalse(mBinderService.areBubblesAllowedForPackage(PKG, mUid));
4094 }
4095
4096 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004097 public void testIsCallerInstantApp_primaryUser() throws Exception {
4098 ApplicationInfo info = new ApplicationInfo();
4099 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4100 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynolds268647a2018-10-25 16:54:27 -04004101 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004102
Julia Reynolds268647a2018-10-25 16:54:27 -04004103 assertTrue(mService.isCallerInstantApp(45770, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004104
4105 info.privateFlags = 0;
Julia Reynolds268647a2018-10-25 16:54:27 -04004106 assertFalse(mService.isCallerInstantApp(575370, 0));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004107 }
4108
4109 @Test
4110 public void testIsCallerInstantApp_secondaryUser() throws Exception {
4111 ApplicationInfo info = new ApplicationInfo();
4112 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
4113 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4114 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
Julia Reynolds268647a2018-10-25 16:54:27 -04004115 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
Julia Reynoldsb6634872018-09-25 13:19:53 -04004116
Julia Reynolds268647a2018-10-25 16:54:27 -04004117 assertTrue(mService.isCallerInstantApp(68638450, 10));
Julia Reynoldsb6634872018-09-25 13:19:53 -04004118 }
4119
4120 @Test
Julia Reynolds86869c92019-06-21 10:45:06 -04004121 public void testIsCallerInstantApp_userAllNotification() throws Exception {
4122 ApplicationInfo info = new ApplicationInfo();
4123 info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
Julia Reynolds57a974b2019-10-07 11:51:47 -04004124 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(USER_SYSTEM)))
Julia Reynolds86869c92019-06-21 10:45:06 -04004125 .thenReturn(info);
4126 when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{"any"});
4127
4128 assertTrue(mService.isCallerInstantApp(45770, UserHandle.USER_ALL));
4129
4130 info.privateFlags = 0;
4131 assertFalse(mService.isCallerInstantApp(575370, UserHandle.USER_ALL ));
4132 }
4133
4134 @Test
Julia Reynoldsb6634872018-09-25 13:19:53 -04004135 public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
4136 ApplicationInfo info = new ApplicationInfo();
4137 info.uid = Binder.getCallingUid();
4138 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
4139 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
4140
4141 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
4142
4143 assertEquals(info.uid, actualUid);
4144 }
4145
4146 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004147 public void testResolveNotificationUid_sameApp() throws Exception {
4148 ApplicationInfo info = new ApplicationInfo();
4149 info.uid = Binder.getCallingUid();
Julia Reynoldsb6634872018-09-25 13:19:53 -04004150 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004151
4152 int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
4153
4154 assertEquals(info.uid, actualUid);
4155 }
4156
4157 @Test
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004158 public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004159 ApplicationInfo info = new ApplicationInfo();
4160 info.uid = Binder.getCallingUid();
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004161 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004162
Julia Reynoldsecc1b572018-10-01 16:19:24 -04004163 int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
4164
4165 assertEquals(info.uid, actualUid);
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004166 }
4167
4168 @Test
4169 public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
4170 ApplicationInfo info = new ApplicationInfo();
4171 info.uid = 1356347;
4172 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
4173
4174 try {
4175 mService.resolveNotificationUid("caller", "caller", 9, 0);
4176 fail("Incorrect uid didn't throw security exception");
4177 } catch (SecurityException e) {
4178 // yay
4179 }
4180 }
4181
4182 @Test
4183 public void testResolveNotificationUid_delegateAllowed() throws Exception {
4184 int expectedUid = 123;
4185
4186 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4187 mService.setPreferencesHelper(mPreferencesHelper);
4188 when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
4189 .thenReturn(true);
4190
4191 assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
4192 }
4193
4194 @Test
4195 public void testResolveNotificationUid_androidAllowed() throws Exception {
4196 int expectedUid = 123;
4197
4198 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
4199 // no delegate
4200
4201 assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
4202 }
4203
4204 @Test
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004205 public void testPostFromAndroidForNonExistentPackage() throws Exception {
4206 final String notReal = "NOT REAL";
4207 when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
4208 PackageManager.NameNotFoundException.class);
4209 ApplicationInfo ai = new ApplicationInfo();
4210 ai.uid = -1;
4211 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4212
4213 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4214 try {
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004215 mInternalService.enqueueNotification(notReal, "android", 0, 0,
4216 "testPostFromAndroidForNonExistentPackage",
Julia Reynoldsa46a7692019-08-15 14:35:46 -04004217 sbn.getId(), sbn.getNotification(), sbn.getUserId());
4218 fail("can't post notifications for nonexistent packages, even if you exist");
4219 } catch (SecurityException e) {
4220 // yay
4221 }
4222 }
4223
4224 @Test
4225 public void testCancelFromAndroidForNonExistentPackage() throws Exception {
4226 final String notReal = "NOT REAL";
4227 when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
4228 PackageManager.NameNotFoundException.class);
4229 ApplicationInfo ai = new ApplicationInfo();
4230 ai.uid = -1;
4231 when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);
4232
4233 // unlike the post case, ignore instead of throwing
4234 final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
4235
4236 mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
4237 sbn.getId(), sbn.getUserId());
4238 }
4239
4240 @Test
Julia Reynoldsa7ba45a2018-08-29 09:07:52 -04004241 public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
4242 when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
4243 // no delegate
4244
4245 try {
4246 mService.resolveNotificationUid("caller", "target", 9, 0);
4247 fail("Incorrect uid didn't throw security exception");
4248 } catch (SecurityException e) {
4249 // yay
4250 }
4251 }
Julia Reynolds564273f2018-09-13 15:53:11 -04004252
4253 @Test
4254 public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
4255 Notification n = new Notification.Builder(mContext, "").build();
4256 n.flags |= FLAG_FOREGROUND_SERVICE;
4257
4258 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4259 n, new UserHandle(mUid), null, 0);
4260 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4261
4262 mService.addEnqueuedNotification(r);
4263
4264 mInternalService.removeForegroundServiceFlagFromNotification(
4265 PKG, r.sbn.getId(), r.sbn.getUserId());
4266
4267 waitForIdle();
4268
4269 verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
4270 }
4271
4272 @Test
4273 public void testRemoveForegroundServiceFlagFromNotification_posted() {
4274 Notification n = new Notification.Builder(mContext, "").build();
4275 n.flags |= FLAG_FOREGROUND_SERVICE;
4276
4277 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
4278 n, new UserHandle(mUid), null, 0);
4279 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4280
4281 mService.addNotification(r);
4282
4283 mInternalService.removeForegroundServiceFlagFromNotification(
4284 PKG, r.sbn.getId(), r.sbn.getUserId());
4285
4286 waitForIdle();
4287
4288 ArgumentCaptor<NotificationRecord> captor =
4289 ArgumentCaptor.forClass(NotificationRecord.class);
4290 verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
4291
4292 assertEquals(0, captor.getValue().getNotification().flags);
4293 }
Beverly58b24532018-10-02 09:08:23 -04004294
4295 @Test
4296 public void testAllowForegroundToasts() throws Exception {
4297 final String testPackage = "testPackageName";
4298 assertEquals(0, mService.mToastQueue.size());
4299 mService.isSystemUid = false;
4300
4301 // package is not suspended
4302 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4303 .thenReturn(false);
4304
4305 // notifications from this package are blocked by the user
4306 mService.setPreferencesHelper(mPreferencesHelper);
4307 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4308
4309 // this app is in the foreground
4310 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND);
4311
4312 // enqueue toast -> toast should still enqueue
4313 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4314 new TestableToastCallback(), 2000, 0);
4315 assertEquals(1, mService.mToastQueue.size());
4316 }
4317
4318 @Test
4319 public void testDisallowToastsFromSuspendedPackages() throws Exception {
4320 final String testPackage = "testPackageName";
4321 assertEquals(0, mService.mToastQueue.size());
4322 mService.isSystemUid = false;
4323
4324 // package is suspended
4325 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4326 .thenReturn(true);
4327
4328 // notifications from this package are NOT blocked by the user
4329 mService.setPreferencesHelper(mPreferencesHelper);
4330 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_LOW);
4331
4332 // enqueue toast -> no toasts enqueued
4333 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4334 new TestableToastCallback(), 2000, 0);
4335 assertEquals(0, mService.mToastQueue.size());
4336 }
4337
4338 @Test
4339 public void testDisallowToastsFromBlockedApps() throws Exception {
4340 final String testPackage = "testPackageName";
4341 assertEquals(0, mService.mToastQueue.size());
4342 mService.isSystemUid = false;
4343
4344 // package is not suspended
4345 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4346 .thenReturn(false);
4347
4348 // notifications from this package are blocked by the user
4349 mService.setPreferencesHelper(mPreferencesHelper);
4350 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4351
4352 // this app is NOT in the foreground
4353 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4354
4355 // enqueue toast -> no toasts enqueued
4356 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4357 new TestableToastCallback(), 2000, 0);
4358 assertEquals(0, mService.mToastQueue.size());
4359 }
4360
4361 @Test
4362 public void testAlwaysAllowSystemToasts() throws Exception {
4363 final String testPackage = "testPackageName";
4364 assertEquals(0, mService.mToastQueue.size());
4365 mService.isSystemUid = true;
4366
4367 // package is suspended
4368 when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
4369 .thenReturn(true);
4370
4371 // notifications from this package ARE blocked by the user
4372 mService.setPreferencesHelper(mPreferencesHelper);
4373 when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
4374
4375 // this app is NOT in the foreground
4376 when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE);
4377
4378 // enqueue toast -> system toast can still be enqueued
4379 ((INotificationManager)mService.mService).enqueueToast(testPackage,
4380 new TestableToastCallback(), 2000, 0);
4381 assertEquals(1, mService.mToastQueue.size());
4382 }
Tony Mak29996702018-11-26 16:23:34 +00004383
4384 @Test
4385 public void testOnNotificationSmartReplySent() {
4386 final int replyIndex = 2;
4387 final String reply = "Hello";
Milo Sredkov13d88112019-02-01 12:23:24 +00004388 final boolean modifiedBeforeSending = true;
Tony Mak29996702018-11-26 16:23:34 +00004389 final boolean generatedByAssistant = true;
4390
4391 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Milo Sredkov13d88112019-02-01 12:23:24 +00004392 r.setSuggestionsGeneratedByAssistant(generatedByAssistant);
Tony Mak29996702018-11-26 16:23:34 +00004393 mService.addNotification(r);
4394
4395 mService.mNotificationDelegate.onNotificationSmartReplySent(
Milo Sredkov13d88112019-02-01 12:23:24 +00004396 r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN,
4397 modifiedBeforeSending);
Tony Mak29996702018-11-26 16:23:34 +00004398 verify(mAssistants).notifyAssistantSuggestedReplySent(
4399 eq(r.sbn), eq(reply), eq(generatedByAssistant));
4400 }
Tony Mak7d4b3a52018-11-27 17:29:36 +00004401
4402 @Test
4403 public void testOnNotificationActionClick() {
4404 final int actionIndex = 2;
4405 final Notification.Action action =
4406 new Notification.Action.Builder(null, "text", null).build();
4407 final boolean generatedByAssistant = false;
4408
4409 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4410 mService.addNotification(r);
4411
4412 NotificationVisibility notificationVisibility =
4413 NotificationVisibility.obtain(r.getKey(), 1, 2, true);
4414 mService.mNotificationDelegate.onNotificationActionClick(
4415 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
4416 generatedByAssistant);
4417 verify(mAssistants).notifyAssistantActionClicked(
4418 eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
4419 }
Gustav Sennton44dc5882018-12-13 14:38:50 +00004420
4421 @Test
4422 public void testLogSmartSuggestionsVisible_triggerOnExpandAndVisible() {
4423 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4424 mService.addNotification(r);
4425
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004426 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4427 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004428 NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
4429 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4430 };
4431 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4432 new NotificationVisibility[0]);
4433
4434 assertEquals(1, mService.countLogSmartSuggestionsVisible);
4435 }
4436
4437 @Test
4438 public void testLogSmartSuggestionsVisible_noTriggerOnExpand() {
4439 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4440 mService.addNotification(r);
4441
Gustav Senntona8e38aa2019-01-22 14:55:39 +00004442 mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
4443 NOTIFICATION_LOCATION_UNKNOWN);
Gustav Sennton44dc5882018-12-13 14:38:50 +00004444
4445 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4446 }
4447
4448 @Test
4449 public void testLogSmartSuggestionsVisible_noTriggerOnVisible() {
4450 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4451 mService.addNotification(r);
4452
Julia Reynolds95334132018-12-19 11:15:35 -05004453 NotificationVisibility[] notificationVisibility = new NotificationVisibility[]{
Gustav Sennton44dc5882018-12-13 14:38:50 +00004454 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
4455 };
4456 mService.mNotificationDelegate.onNotificationVisibilityChanged(notificationVisibility,
4457 new NotificationVisibility[0]);
4458
4459 assertEquals(0, mService.countLogSmartSuggestionsVisible);
4460 }
Julia Reynolds95334132018-12-19 11:15:35 -05004461
4462 public void testReportSeen_delegated() {
4463 Notification.Builder nb =
4464 new Notification.Builder(mContext, mTestNotificationChannel.getId())
4465 .setContentTitle("foo")
4466 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4467
4468 StatusBarNotification sbn = new StatusBarNotification(PKG, "opPkg", 0, "tag", mUid, 0,
4469 nb.build(), new UserHandle(mUid), null, 0);
4470 NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4471
4472 mService.reportSeen(r);
4473 verify(mAppUsageStats, never()).reportEvent(anyString(), anyInt(), anyInt());
4474
4475 }
4476
4477 @Test
4478 public void testReportSeen_notDelegated() {
4479 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4480
4481 mService.reportSeen(r);
4482 verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
4483 }
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004484
4485 @Test
4486 public void testNotificationStats_notificationError() {
4487 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
4488 mService.addNotification(r);
4489
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004490 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.sbn.getId(),
4491 r.sbn.getTag(), mUid, 0,
Julia Reynolds3207e2f2018-12-20 09:39:53 -05004492 new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
4493 new UserHandle(mUid), null, 0);
4494 NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4495 mService.addEnqueuedNotification(update);
4496 assertNull(update.sbn.getNotification().getSmallIcon());
4497
4498 NotificationManagerService.PostNotificationRunnable runnable =
4499 mService.new PostNotificationRunnable(update.getKey());
4500 runnable.run();
4501 waitForIdle();
4502
4503 ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
4504 verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
4505 assertNotNull(captor.getValue());
4506 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00004507
4508 @Test
Julia Reynolds7a6d07a2019-03-18 11:31:56 -04004509 public void testCanNotifyAsUser_crossUser() throws Exception {
4510 // same user no problem
4511 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId());
4512
4513 // cross user, no permission, problem
4514 try {
4515 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4516 fail("Should not be callable cross user without cross user permission");
4517 } catch (SecurityException e) {
4518 // good
4519 }
4520
4521 // cross user, with permission, no problem
4522 TestablePermissions perms = mContext.getTestablePermissions();
4523 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4524 mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1);
4525 }
4526
4527 @Test
Julia Reynoldsb4a9e9c2019-03-20 15:46:08 -04004528 public void testgetNotificationChannels_crossUser() throws Exception {
4529 // same user no problem
4530 mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
4531
4532 // cross user, no permission, problem
4533 try {
4534 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4535 fail("Should not be callable cross user without cross user permission");
4536 } catch (SecurityException e) {
4537 // good
4538 }
4539
4540 // cross user, with permission, no problem
4541 TestablePermissions perms = mContext.getTestablePermissions();
4542 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
4543 mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
4544 }
4545
4546 @Test
Tony Mak9a3c1f12019-03-04 16:04:42 +00004547 public void setDefaultAssistantForUser_fromConfigXml() {
4548 clearDeviceConfig();
4549 ComponentName xmlConfig = new ComponentName("config", "xml");
Jay Aliomer4204f252019-08-26 11:36:53 -04004550 ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004551 when(mResources
4552 .getString(
4553 com.android.internal.R.string.config_defaultAssistantAccessComponent))
4554 .thenReturn(xmlConfig.flattenToString());
4555 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04004556 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
4557 .thenReturn(components);
4558 when(mAssistants.getDefaultComponents())
4559 .thenReturn(components);
Tony Mak9a3c1f12019-03-04 16:04:42 +00004560 mService.setNotificationAssistantAccessGrantedCallback(
4561 mNotificationAssistantAccessGrantedCallback);
4562
Jay Aliomer4204f252019-08-26 11:36:53 -04004563
Tony Mak9a3c1f12019-03-04 16:04:42 +00004564 mService.setDefaultAssistantForUser(0);
4565
4566 verify(mNotificationAssistantAccessGrantedCallback)
4567 .onGranted(eq(xmlConfig), eq(0), eq(true));
4568 }
4569
4570 @Test
4571 public void setDefaultAssistantForUser_fromDeviceConfig() {
4572 ComponentName xmlConfig = new ComponentName("xml", "config");
4573 ComponentName deviceConfig = new ComponentName("device", "config");
4574 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4575 when(mResources
4576 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4577 .thenReturn(xmlConfig.flattenToString());
4578 when(mContext.getResources()).thenReturn(mResources);
Jay Aliomer4204f252019-08-26 11:36:53 -04004579 when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
Tony Mak9a3c1f12019-03-04 16:04:42 +00004580 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Jay Aliomer4204f252019-08-26 11:36:53 -04004581 when(mAssistants.getDefaultComponents())
4582 .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004583 mService.setNotificationAssistantAccessGrantedCallback(
4584 mNotificationAssistantAccessGrantedCallback);
4585
4586 mService.setDefaultAssistantForUser(0);
4587
4588 verify(mNotificationAssistantAccessGrantedCallback)
4589 .onGranted(eq(deviceConfig), eq(0), eq(true));
4590 }
4591
4592 @Test
4593 public void setDefaultAssistantForUser_deviceConfigInvalid() {
4594 ComponentName xmlConfig = new ComponentName("xml", "config");
4595 ComponentName deviceConfig = new ComponentName("device", "config");
4596 setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
4597 when(mResources
4598 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
4599 .thenReturn(xmlConfig.flattenToString());
4600 when(mContext.getResources()).thenReturn(mResources);
4601 // Only xmlConfig is valid, deviceConfig is not.
4602 when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
Jay Aliomer4204f252019-08-26 11:36:53 -04004603 .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
4604 when(mAssistants.getDefaultComponents())
4605 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
Tony Mak9a3c1f12019-03-04 16:04:42 +00004606 mService.setNotificationAssistantAccessGrantedCallback(
4607 mNotificationAssistantAccessGrantedCallback);
4608
4609 mService.setDefaultAssistantForUser(0);
4610
4611 verify(mNotificationAssistantAccessGrantedCallback)
4612 .onGranted(eq(xmlConfig), eq(0), eq(true));
4613 }
4614
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004615 @Test
Jay Aliomer4204f252019-08-26 11:36:53 -04004616 public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
4617 ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
4618 generateResetComponentValues();
4619 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
4620 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
4621 ComponentName deviceConfig1 = new ComponentName("device", "config1");
4622 ComponentName deviceConfig2 = new ComponentName("device", "config2");
4623 changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
4624 changes.put(false, new ArrayList());
4625 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
4626 mService.getBinderService().clearData("device", 0, false);
4627 verify(mAssistants, times(1))
4628 .setPackageOrComponentEnabled(
4629 eq("device/config2"),
4630 eq(0), eq(true), eq(false));
4631 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4632 eq("device"), eq(0), eq(false), eq(true));
4633 }
4634
4635 @Test
4636 public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
4637 ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
4638 generateResetComponentValues();
4639 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
4640 ComponentName deviceConfig = new ComponentName("device", "config");
4641 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
4642 changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
4643 changes.put(false, new ArrayList());
4644 when(mListeners.resetComponents(anyString(), anyInt()))
4645 .thenReturn(changes);
4646 mService.getBinderService().clearData("device", 0, false);
4647 verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
4648 eq("device"), eq(0), eq(false), eq(true));
4649 }
4650
4651 @Test
4652 public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
4653 ComponentName deviceConfig = new ComponentName("device", "config");
4654 ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
4655 when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
4656 when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
4657 mService.getBinderService().clearData("device", 0, false);
4658 verify(mConditionProviders, times(1)).resetPackage(
4659 eq("device"), eq(0));
4660 }
4661
4662 @Test
Mady Mellor65dcaa92019-04-03 12:21:44 -07004663 public void testFlagBubble() throws RemoteException {
4664 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004665 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor65dcaa92019-04-03 12:21:44 -07004666
4667 // Notif with bubble metadata but not our other misc requirements
4668 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4669 null /* tvExtender */, true /* isBubble */);
4670
4671 // Say we're foreground
4672 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4673 IMPORTANCE_FOREGROUND);
4674
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004675 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor65dcaa92019-04-03 12:21:44 -07004676 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4677 waitForIdle();
4678
4679 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4680 assertEquals(1, notifs.length);
4681 assertTrue((notifs[0].getNotification().flags & FLAG_BUBBLE) != 0);
4682 assertTrue(mService.getNotificationRecord(
4683 nr.sbn.getKey()).getNotification().isBubbleNotification());
4684 }
4685
4686 @Test
Mady Mellorc6820342019-05-20 12:04:36 -07004687 public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
4688 // Bubbles are allowed!
4689 setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
4690
4691 // Notif with bubble metadata but not our other misc requirements
4692 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4693 null /* tvExtender */, true /* isBubble */);
4694
4695 // Say we're foreground
4696 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4697 IMPORTANCE_FOREGROUND);
4698
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004699 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorc6820342019-05-20 12:04:36 -07004700 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4701 waitForIdle();
4702
4703 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4704 assertEquals(1, notifs.length);
4705 assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
4706 assertFalse(mService.getNotificationRecord(
4707 nr.sbn.getKey()).getNotification().isBubbleNotification());
4708 }
4709
4710 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004711 public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004712 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004713 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004714
Mady Mellorbe797962019-04-01 16:04:24 -07004715 // Notif with bubble metadata but not our other misc requirements
4716 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4717 null /* tvExtender */, true /* isBubble */);
4718
4719 // Say we're foreground
4720 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4721 IMPORTANCE_FOREGROUND);
4722
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004723 mBinderService.enqueueNotificationWithTag(PKG, PKG,
4724 nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
Mady Mellorbe797962019-04-01 16:04:24 -07004725 waitForIdle();
4726
4727 // yes allowed, yes foreground, yes bubble
4728 assertTrue(mService.getNotificationRecord(
4729 nr.sbn.getKey()).getNotification().isBubbleNotification());
4730 }
4731
4732 @Test
4733 public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
4734 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004735 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004736
4737 // Notif with bubble metadata but not our other misc requirements
4738 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
4739 null /* tvExtender */, true /* isBubble */);
4740
4741 // Make sure we're NOT foreground
4742 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
4743 IMPORTANCE_VISIBLE);
4744
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004745 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004746 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4747 waitForIdle();
4748
4749 // yes allowed but NOT foreground, no bubble
4750 assertFalse(mService.getNotificationRecord(
4751 nr.sbn.getKey()).getNotification().isBubbleNotification());
4752 }
4753
4754 @Test
4755 public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
4756 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004757 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004758
4759 // Notif with bubble metadata but not our other misc requirements
4760 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4761 null /* tvExtender */, true /* isBubble */);
4762
4763 // Send notif when we're foreground
4764 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4765 IMPORTANCE_FOREGROUND);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004766 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004767 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4768 waitForIdle();
4769
4770 // yes allowed, yes foreground, yes bubble
4771 assertTrue(mService.getNotificationRecord(
4772 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4773
4774 // Send a new update when we're not foreground
4775 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4776 null /* tvExtender */, true /* isBubble */);
4777
4778 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4779 IMPORTANCE_VISIBLE);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004780 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004781 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4782 waitForIdle();
4783
4784 // yes allowed, previously foreground / flagged, yes bubble
4785 assertTrue(mService.getNotificationRecord(
4786 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4787
4788 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4789 assertEquals(1, notifs2.length);
4790 assertEquals(1, mService.getNotificationRecordCount());
4791 }
4792
4793 @Test
4794 public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
4795 throws RemoteException {
4796 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004797 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004798
4799 // Notif with bubble metadata but not our other misc requirements
4800 NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
4801 null /* tvExtender */, true /* isBubble */);
4802
4803 // Send notif when we're foreground
4804 when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
4805 IMPORTANCE_FOREGROUND);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004806 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004807 nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
4808 waitForIdle();
4809
4810 // yes allowed, yes foreground, yes bubble
4811 assertTrue(mService.getNotificationRecord(
4812 nr1.sbn.getKey()).getNotification().isBubbleNotification());
4813
4814 // Remove the bubble
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004815 mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), nr1.sbn.getId(),
Mady Mellorbe797962019-04-01 16:04:24 -07004816 nr1.sbn.getUserId());
4817 waitForIdle();
4818
4819 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
4820 assertEquals(0, notifs.length);
4821 assertEquals(0, mService.getNotificationRecordCount());
4822
4823 // Send a new update when we're not foreground
4824 NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
4825 null /* tvExtender */, true /* isBubble */);
4826
4827 when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
4828 IMPORTANCE_VISIBLE);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004829 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004830 nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
4831 waitForIdle();
4832
4833 // yes allowed, but was removed & no foreground, so no bubble
4834 assertFalse(mService.getNotificationRecord(
4835 nr2.sbn.getKey()).getNotification().isBubbleNotification());
4836
4837 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
4838 assertEquals(1, notifs2.length);
4839 assertEquals(1, mService.getNotificationRecordCount());
4840 }
4841
4842 @Test
4843 public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
4844 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004845 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004846
4847 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004848 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07004849 // Give it a person
4850 Person person = new Person.Builder()
4851 .setName("bubblebot")
4852 .build();
Mady Mellora10448e2019-04-26 13:50:58 -07004853 // It needs remote input to be bubble-able
4854 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
4855 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
4856 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
4857 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
4858 inputIntent).addRemoteInput(remoteInput)
4859 .build();
Mady Mellorbe797962019-04-01 16:04:24 -07004860 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004861 Notification.Builder nb = new Notification.Builder(mContext,
4862 mTestNotificationChannel.getId())
4863 .setContentTitle("foo")
4864 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07004865 .setStyle(new Notification.MessagingStyle(person)
4866 .setConversationTitle("Bubble Chat")
4867 .addMessage("Hello?",
4868 SystemClock.currentThreadTimeMillis() - 300000, person)
4869 .addMessage("Is it me you're looking for?",
4870 SystemClock.currentThreadTimeMillis(), person)
4871 )
Mady Mellora10448e2019-04-26 13:50:58 -07004872 .setActions(replyAction)
Mady Mellorbe797962019-04-01 16:04:24 -07004873 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4874
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004875 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4876 "testFlagBubbleNotifs_flag_messaging", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07004877 nb.build(), new UserHandle(mUid), null, 0);
4878 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4879
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004880 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004881 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4882 waitForIdle();
4883
4884 // yes allowed, yes messaging, yes bubble
4885 assertTrue(mService.getNotificationRecord(
4886 sbn.getKey()).getNotification().isBubbleNotification());
4887 }
4888
4889 @Test
4890 public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
4891 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004892 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004893
4894 // Give it bubble metadata
4895 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4896 // Give it a person
4897 Person person = new Person.Builder()
4898 .setName("bubblebot")
4899 .build();
4900 // Make it a phone call
4901 Notification.Builder nb = new Notification.Builder(mContext,
4902 mTestNotificationChannel.getId())
4903 .setCategory(CATEGORY_CALL)
4904 .addPerson(person)
4905 .setContentTitle("foo")
4906 .setBubbleMetadata(data)
4907 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4908
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004909 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4910 "testFlagBubbleNotifs_flag_phonecall", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07004911 nb.build(), new UserHandle(mUid), null, 0);
4912 // Make sure it has foreground service
4913 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4914 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4915
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004916 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004917 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4918 waitForIdle();
4919
4920 // yes phone call, yes person, yes foreground service, yes bubble
4921 assertTrue(mService.getNotificationRecord(
4922 sbn.getKey()).getNotification().isBubbleNotification());
4923 }
4924
4925 @Test
4926 public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
4927 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004928 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004929
4930 // Give it bubble metadata
4931 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4932 // Give it a person
4933 Person person = new Person.Builder()
4934 .setName("bubblebot")
4935 .build();
4936 // Make it a phone call
4937 Notification.Builder nb = new Notification.Builder(mContext,
4938 mTestNotificationChannel.getId())
4939 .setCategory(CATEGORY_CALL)
4940 .addPerson(person)
4941 .setContentTitle("foo")
4942 .setBubbleMetadata(data)
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004943 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4944
4945 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
4946 nb.build(), new UserHandle(mUid), null, 0);
4947 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4948
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004949 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004950 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4951 waitForIdle();
4952
Mady Mellorbe797962019-04-01 16:04:24 -07004953 // yes phone call, yes person, NO foreground service, no bubble
4954 assertFalse(mService.getNotificationRecord(
Mady Mellor7eb18ef2019-03-27 14:03:46 -07004955 sbn.getKey()).getNotification().isBubbleNotification());
4956 }
4957
4958 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07004959 public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
4960 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004961 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004962
4963 // Give it bubble metadata
4964 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4965 // Make it a phone call
4966 Notification.Builder nb = new Notification.Builder(mContext,
4967 mTestNotificationChannel.getId())
4968 .setCategory(CATEGORY_CALL)
4969 .setContentTitle("foo")
4970 .setBubbleMetadata(data)
4971 .setSmallIcon(android.R.drawable.sym_def_app_icon);
4972
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004973 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
4974 "testFlagBubbleNotifs_noFlag_phonecall_noPerson", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07004975 nb.build(), new UserHandle(mUid), null, 0);
4976 // Make sure it has foreground service
4977 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
4978 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
4979
Julia Reynoldsb6c83742019-07-30 18:03:40 -04004980 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07004981 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
4982 waitForIdle();
4983
4984 // yes phone call, yes foreground service, BUT NO person, no bubble
4985 assertFalse(mService.getNotificationRecord(
4986 sbn.getKey()).getNotification().isBubbleNotification());
4987 }
4988
4989 @Test
4990 public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
4991 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07004992 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07004993
4994 // Give it bubble metadata
4995 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
4996 // Give it a person
4997 Person person = new Person.Builder()
4998 .setName("bubblebot")
4999 .build();
5000 // No category
5001 Notification.Builder nb = new Notification.Builder(mContext,
5002 mTestNotificationChannel.getId())
5003 .addPerson(person)
5004 .setContentTitle("foo")
5005 .setBubbleMetadata(data)
5006 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5007
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005008 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5009 "testFlagBubbleNotifs_noFlag_phonecall_noCategory", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005010 nb.build(), new UserHandle(mUid), null, 0);
5011 // Make sure it has foreground service
5012 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5013 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5014
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005015 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005016 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5017 waitForIdle();
5018
5019 // yes person, yes foreground service, BUT NO call, no bubble
5020 assertFalse(mService.getNotificationRecord(
5021 sbn.getKey()).getNotification().isBubbleNotification());
5022 }
5023
5024 @Test
5025 public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005026 // Bubbles are NOT allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005027 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005028
Mady Mellorbe797962019-04-01 16:04:24 -07005029 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005030 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005031 // Give it a person
5032 Person person = new Person.Builder()
5033 .setName("bubblebot")
5034 .build();
5035 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005036 Notification.Builder nb = new Notification.Builder(mContext,
5037 mTestNotificationChannel.getId())
5038 .setContentTitle("foo")
5039 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07005040 .setStyle(new Notification.MessagingStyle(person)
5041 .setConversationTitle("Bubble Chat")
5042 .addMessage("Hello?",
5043 SystemClock.currentThreadTimeMillis() - 300000, person)
5044 .addMessage("Is it me you're looking for?",
5045 SystemClock.currentThreadTimeMillis(), person)
5046 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005047 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5048
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005049 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5050 "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed", mUid, 0,
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005051 nb.build(), new UserHandle(mUid), null, 0);
5052 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5053
5054 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005055 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005056 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5057 waitForIdle();
5058
5059 // not allowed, no bubble
5060 assertFalse(mService.getNotificationRecord(
5061 sbn.getKey()).getNotification().isBubbleNotification());
5062 }
5063
5064 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005065 public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005066 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005067 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005068
5069 // Notif WITHOUT bubble metadata
Mady Mellorbe797962019-04-01 16:04:24 -07005070 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005071
5072 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005073 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005074 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5075 waitForIdle();
5076
5077 // no bubble metadata, no bubble
5078 assertFalse(mService.getNotificationRecord(
Mady Mellorbe797962019-04-01 16:04:24 -07005079 nr.sbn.getKey()).getNotification().isBubbleNotification());
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005080 }
5081
5082 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005083 public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005084 // Bubbles are allowed except on this channel
5085 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005086
Mady Mellorbe797962019-04-01 16:04:24 -07005087 // Give it bubble metadata
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005088 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
Mady Mellorbe797962019-04-01 16:04:24 -07005089 // Give it a person
5090 Person person = new Person.Builder()
5091 .setName("bubblebot")
5092 .build();
5093 // Make it messaging style
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005094 Notification.Builder nb = new Notification.Builder(mContext,
5095 mTestNotificationChannel.getId())
5096 .setContentTitle("foo")
5097 .setBubbleMetadata(data)
Mady Mellorbe797962019-04-01 16:04:24 -07005098 .setStyle(new Notification.MessagingStyle(person)
5099 .setConversationTitle("Bubble Chat")
5100 .addMessage("Hello?",
5101 SystemClock.currentThreadTimeMillis() - 300000, person)
5102 .addMessage("Is it me you're looking for?",
5103 SystemClock.currentThreadTimeMillis(), person)
5104 )
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005105 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5106
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005107 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5108 "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed", mUid, 0,
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005109 nb.build(), new UserHandle(mUid), null, 0);
5110 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5111
5112 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005113 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellor7eb18ef2019-03-27 14:03:46 -07005114 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5115 waitForIdle();
5116
5117 // channel not allowed, no bubble
5118 assertFalse(mService.getNotificationRecord(
5119 sbn.getKey()).getNotification().isBubbleNotification());
5120 }
Tony Mak9a3c1f12019-03-04 16:04:42 +00005121
Mady Mellor49b1bf12019-03-29 12:00:02 -07005122 @Test
Mady Mellorbe797962019-04-01 16:04:24 -07005123 public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005124 // Bubbles are not allowed!
5125 setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005126
5127 // Give it bubble metadata
5128 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
5129 // Give it a person
5130 Person person = new Person.Builder()
5131 .setName("bubblebot")
5132 .build();
5133 // Make it a phone call
5134 Notification.Builder nb = new Notification.Builder(mContext,
5135 mTestNotificationChannel.getId())
5136 .setCategory(CATEGORY_CALL)
5137 .addPerson(person)
5138 .setContentTitle("foo")
5139 .setBubbleMetadata(data)
5140 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5141
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005142 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5143 "testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005144 nb.build(), new UserHandle(mUid), null, 0);
5145 // Make sure it has foreground service
5146 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5147 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5148
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005149 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005150 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5151 waitForIdle();
5152
5153 // yes phone call, yes person, yes foreground service, but not allowed, no bubble
5154 assertFalse(mService.getNotificationRecord(
5155 sbn.getKey()).getNotification().isBubbleNotification());
5156 }
5157
5158 @Test
5159 public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
Mady Mellorc6820342019-05-20 12:04:36 -07005160 // Bubbles are allowed, but not on channel.
5161 setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
Mady Mellorbe797962019-04-01 16:04:24 -07005162
5163 // Give it bubble metadata
5164 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
5165 // Give it a person
5166 Person person = new Person.Builder()
5167 .setName("bubblebot")
5168 .build();
5169 // Make it a phone call
5170 Notification.Builder nb = new Notification.Builder(mContext,
5171 mTestNotificationChannel.getId())
5172 .setCategory(CATEGORY_CALL)
5173 .addPerson(person)
5174 .setContentTitle("foo")
5175 .setBubbleMetadata(data)
5176 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5177
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005178 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
5179 "testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", mUid, 0,
Mady Mellorbe797962019-04-01 16:04:24 -07005180 nb.build(), new UserHandle(mUid), null, 0);
5181 // Make sure it has foreground service
5182 sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
5183 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5184
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005185 mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
Mady Mellorbe797962019-04-01 16:04:24 -07005186 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5187 waitForIdle();
5188
5189 // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
5190 assertFalse(mService.getNotificationRecord(
5191 sbn.getKey()).getNotification().isBubbleNotification());
5192 }
5193
5194 @Test
Mady Mellor49b1bf12019-03-29 12:00:02 -07005195 public void testCancelAllNotifications_cancelsBubble() throws Exception {
5196 final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
5197 nr.sbn.getNotification().flags |= FLAG_BUBBLE;
5198 mService.addNotification(nr);
5199
5200 mBinderService.cancelAllNotifications(PKG, nr.sbn.getUserId());
5201 waitForIdle();
5202
5203 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5204 assertEquals(0, notifs.length);
5205 assertEquals(0, mService.getNotificationRecordCount());
5206 }
5207
5208 @Test
5209 public void testAppCancelNotifications_cancelsBubbles() throws Exception {
5210 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5211 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5212
5213 // Post the notification
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005214 mBinderService.enqueueNotificationWithTag(PKG, PKG,
5215 "testAppCancelNotifications_cancelsBubbles",
Mady Mellor49b1bf12019-03-29 12:00:02 -07005216 nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId());
5217 waitForIdle();
5218
5219 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5220 assertEquals(1, notifs.length);
5221 assertEquals(1, mService.getNotificationRecordCount());
5222
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005223 mBinderService.cancelNotificationWithTag(PKG, PKG,
5224 "testAppCancelNotifications_cancelsBubbles", nrBubble.sbn.getId(),
Mady Mellor49b1bf12019-03-29 12:00:02 -07005225 nrBubble.sbn.getUserId());
5226 waitForIdle();
5227
5228 StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
5229 assertEquals(0, notifs2.length);
5230 assertEquals(0, mService.getNotificationRecordCount());
5231 }
5232
5233 @Test
5234 public void testCancelAllNotificationsFromListener_ignoresBubbles() throws Exception {
5235 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5236 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5237 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5238
5239 mService.addNotification(nrNormal);
5240 mService.addNotification(nrBubble);
5241
5242 mService.getBinderService().cancelNotificationsFromListener(null, null);
5243 waitForIdle();
5244
5245 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5246 assertEquals(1, notifs.length);
5247 assertEquals(1, mService.getNotificationRecordCount());
5248 }
5249
5250 @Test
5251 public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
5252 final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
5253 final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
5254 nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE;
5255
5256 mService.addNotification(nrNormal);
5257 mService.addNotification(nrBubble);
5258
5259 String[] keys = {nrNormal.sbn.getKey(), nrBubble.sbn.getKey()};
5260 mService.getBinderService().cancelNotificationsFromListener(null, keys);
5261 waitForIdle();
5262
5263 StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
5264 assertEquals(1, notifs.length);
5265 assertEquals(1, mService.getNotificationRecordCount());
5266 }
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005267
Julia Reynolds4214da92019-04-10 15:04:06 -04005268 @Test
Julia Reynolds088c4482019-04-10 12:43:27 -04005269 public void testGetAllowedAssistantAdjustments() throws Exception {
5270 List<String> capabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005271 assertNotNull(capabilities);
5272
5273 for (int i = capabilities.size() - 1; i >= 0; i--) {
5274 String capability = capabilities.get(i);
Julia Reynolds088c4482019-04-10 12:43:27 -04005275 mBinderService.disallowAssistantAdjustment(capability);
5276 assertEquals(i + 1, mBinderService.getAllowedAssistantAdjustments(null).size());
5277 List<String> currentCapabilities = mBinderService.getAllowedAssistantAdjustments(null);
Julia Reynoldsad6dd352019-03-07 16:46:22 -05005278 assertNotNull(currentCapabilities);
5279 assertFalse(currentCapabilities.contains(capability));
5280 }
5281 }
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005282
Julia Reynolds4214da92019-04-10 15:04:06 -04005283 @Test
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005284 public void testAdjustRestrictedKey() throws Exception {
5285 NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
Julia Reynolds4214da92019-04-10 15:04:06 -04005286 mService.addNotification(r);
5287 when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
Julia Reynoldsc7dcdc22019-03-25 10:26:14 -04005288
5289 when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
5290 when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
5291
5292 Bundle signals = new Bundle();
5293 signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
5294 signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
5295 Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
5296 "", r.getUser().getIdentifier());
5297
5298 mBinderService.applyAdjustmentFromAssistant(null, adjustment);
5299 r.applyAdjustments();
5300
5301 assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
5302 assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
5303 }
Julia Reynolds657d1642019-03-27 12:15:57 -04005304
Julia Reynolds4214da92019-04-10 15:04:06 -04005305 @Test
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005306 public void testAutomaticZenRuleValidation_policyFilterAgreement() throws Exception {
Julia Reynolds4214da92019-04-10 15:04:06 -04005307 when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
5308 .thenReturn(true);
5309 mService.setZenHelper(mock(ZenModeHelper.class));
5310 ComponentName owner = new ComponentName(mContext, this.getClass());
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005311 ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
5312 boolean isEnabled = true;
5313 AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5314 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5315
5316 try {
5317 mBinderService.addAutomaticZenRule(rule);
Julia Reynolds4214da92019-04-10 15:04:06 -04005318 fail("Zen policy only applies to priority only mode");
Julia Reynoldsa94365d2019-04-09 10:48:43 -04005319 } catch (IllegalArgumentException e) {
5320 // yay
5321 }
5322
5323 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5324 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
5325 mBinderService.addAutomaticZenRule(rule);
5326
5327 rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
5328 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
5329 mBinderService.addAutomaticZenRule(rule);
5330 }
5331
Julia Reynolds4214da92019-04-10 15:04:06 -04005332 @Test
Julia Reynolds657d1642019-03-27 12:15:57 -04005333 public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
5334 try {
5335 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5336 mUid + UserHandle.PER_USER_RANGE);
5337 fail("Cannot call cross user without permission");
5338 } catch (SecurityException e) {
5339 // pass
5340 }
5341
5342 // cross user, with permission, no problem
5343 TestablePermissions perms = mContext.getTestablePermissions();
5344 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5345 mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
5346 mUid + UserHandle.PER_USER_RANGE);
5347 }
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005348
Julia Reynolds4214da92019-04-10 15:04:06 -04005349 @Test
Julia Reynolds2f7592d2019-03-27 12:17:23 -04005350 public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
5351 try {
5352 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5353 mUid + UserHandle.PER_USER_RANGE);
5354 fail("Cannot call cross user without permission");
5355 } catch (SecurityException e) {
5356 // pass
5357 }
5358
5359 // cross user, with permission, no problem
5360 TestablePermissions perms = mContext.getTestablePermissions();
5361 perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
5362 mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
5363 mUid + UserHandle.PER_USER_RANGE);
5364 }
Mady Mellora54e9fa2019-04-18 13:26:18 -07005365
5366 @Test
5367 public void testNotificationBubbleChanged_false() throws Exception {
5368 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005369 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005370
5371 // Notif with bubble metadata but not our other misc requirements
5372 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5373 null /* tvExtender */, true /* isBubble */);
5374
5375 // Say we're foreground
5376 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5377 IMPORTANCE_FOREGROUND);
5378
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005379 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005380 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5381 waitForIdle();
5382
Mady Mellor66efd5e2019-05-15 13:38:11 -07005383 // Reset as this is called when the notif is first sent
5384 reset(mListeners);
5385
Mady Mellora54e9fa2019-04-18 13:26:18 -07005386 // First we were a bubble
5387 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5388 assertEquals(1, notifsBefore.length);
5389 assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
5390
5391 // Notify we're not a bubble
5392 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
5393 waitForIdle();
5394
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005395 // Make sure we are not a bubble
5396 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5397 assertEquals(1, notifsAfter.length);
5398 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005399 }
5400
5401 @Test
5402 public void testNotificationBubbleChanged_true() throws Exception {
5403 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005404 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005405
5406 // Plain notification that has bubble metadata
5407 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5408 null /* tvExtender */, true /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005409 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005410 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5411 waitForIdle();
5412
5413 // Would be a normal notification because wouldn't have met requirements to bubble
5414 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5415 assertEquals(1, notifsBefore.length);
5416 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5417
5418 // Make the package foreground so that we're allowed to be a bubble
5419 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5420 IMPORTANCE_FOREGROUND);
5421
Mady Mellor66efd5e2019-05-15 13:38:11 -07005422 // Reset as this is called when the notif is first sent
5423 reset(mListeners);
5424
Mady Mellora54e9fa2019-04-18 13:26:18 -07005425 // Notify we are now a bubble
5426 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5427 waitForIdle();
5428
Mady Mellor3a0a1b42019-05-23 06:40:21 -07005429 // Make sure we are a bubble
5430 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5431 assertEquals(1, notifsAfter.length);
5432 assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005433 }
5434
5435 @Test
5436 public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
5437 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005438 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellora54e9fa2019-04-18 13:26:18 -07005439
5440 // Notif that is not a bubble
5441 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5442 null /* tvExtender */, true /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005443 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellora54e9fa2019-04-18 13:26:18 -07005444 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5445 waitForIdle();
5446
Mady Mellor66efd5e2019-05-15 13:38:11 -07005447 // Reset as this is called when the notif is first sent
5448 reset(mListeners);
5449
Mady Mellora54e9fa2019-04-18 13:26:18 -07005450 // Would be a normal notification because wouldn't have met requirements to bubble
5451 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5452 assertEquals(1, notifsBefore.length);
5453 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5454
5455 // Notify we are now a bubble
5456 mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
5457 waitForIdle();
5458
5459 // We still wouldn't be a bubble because the notification didn't meet requirements
5460 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5461 assertEquals(1, notifsAfter.length);
5462 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
5463 }
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005464
5465 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005466 public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
5467 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5468 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5469 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5470 waitForIdle();
5471
5472 // A notification exists for the given record
5473 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5474 assertEquals(1, notifsBefore.length);
5475
5476 reset(mPackageManager);
5477
5478 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5479
5480 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Aran Ink979c9762019-10-24 16:09:45 -04005481 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005482
5483 // Grant permission called for the UID of SystemUI under the target user ID
5484 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5485 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5486 eq(nr.sbn.getUserId()));
5487 }
5488
5489 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005490 public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
5491 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5492 waitForIdle();
5493
5494 // No notifications exist for the given record
5495 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5496 assertEquals(0, notifsBefore.length);
5497
5498 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5499 int uid = 0; // sysui on primary user
5500
5501 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5502 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5503
5504 // Grant permission still called if no NotificationRecord exists for the given key
5505 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5506 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5507 eq(nr.sbn.getUserId()));
5508 }
5509
5510 @Test
Aran Inkfd2bfd32019-10-04 16:30:01 -04005511 public void testGrantInlineReplyUriPermission_userAll() throws Exception {
5512 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5513 NotificationRecord nr =
5514 generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
5515 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5516 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5517 waitForIdle();
5518
5519 // A notification exists for the given record
5520 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5521 assertEquals(1, notifsBefore.length);
5522
5523 reset(mPackageManager);
5524
5525 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5526
5527 mService.mNotificationDelegate.grantInlineReplyUriPermission(
Aran Ink979c9762019-10-24 16:09:45 -04005528 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005529
5530 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5531 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5532 eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5533 eq(UserHandle.USER_SYSTEM));
5534 }
5535
5536 @Test
5537 public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
5538 // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
5539 int otherUserId = 11;
5540 NotificationRecord nr =
5541 generateNotificationRecord(mTestNotificationChannel, otherUserId);
5542 mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
5543 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5544 waitForIdle();
5545
5546 // A notification exists for the given record
5547 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5548 assertEquals(1, notifsBefore.length);
5549
5550 reset(mPackageManager);
5551
5552 Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5553
5554 int uid = 0; // sysui on primary user
Aran Ink979c9762019-10-24 16:09:45 -04005555 int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
Aran Inkfd2bfd32019-10-04 16:30:01 -04005556 String sysuiPackage = "sysui";
5557 final String[] sysuiPackages = new String[] { sysuiPackage };
5558 when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
5559
5560 // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
5561 // time this is called
5562 when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
5563 .thenReturn(otherUserUid);
5564
Aran Ink979c9762019-10-24 16:09:45 -04005565 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5566 nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), uid);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005567
5568 // Target user for the grant is USER_ALL instead of USER_SYSTEM
5569 verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
5570 eq(otherUserUid), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
5571 eq(otherUserId));
5572 }
5573
5574 @Test
Aran Ink979c9762019-10-24 16:09:45 -04005575 public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
5576 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5577 reset(mPackageManager);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005578
Aran Ink979c9762019-10-24 16:09:45 -04005579 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5580 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
Aran Inkfd2bfd32019-10-04 16:30:01 -04005581
Aran Ink979c9762019-10-24 16:09:45 -04005582 // create an inline record with two uris in it
5583 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5584 nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5585 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5586 nr.getKey(), uri2, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
Aran Inkfd2bfd32019-10-04 16:30:01 -04005587
Aran Ink979c9762019-10-24 16:09:45 -04005588 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5589 assertNotNull(record); // record exists
5590 assertEquals(record.getUris().size(), 2); // record has two uris in it
Aran Inkfd2bfd32019-10-04 16:30:01 -04005591
Aran Ink979c9762019-10-24 16:09:45 -04005592 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5593
5594 // permissionOwner destroyed
5595 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5596 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
5597 }
5598
5599
5600 @Test
5601 public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
5602 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
5603 reset(mPackageManager);
5604
5605 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5606
5607 // no permissionOwner destroyed
5608 verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
5609 any(), eq(null), eq(~0), eq(nr.getUserId()));
5610 }
5611
5612 @Test
5613 public void testClearInlineReplyUriPermission_userAll() throws Exception {
5614 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5615 UserHandle.USER_ALL);
5616 reset(mPackageManager);
5617
5618 Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
5619 Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
5620
5621 // create an inline record a uri in it
5622 mService.mNotificationDelegate.grantInlineReplyUriPermission(
5623 nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
5624
5625 InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
5626 assertNotNull(record); // record exists
5627
5628 mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
5629
5630 // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
5631 verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
5632 eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
Aran Inkfd2bfd32019-10-04 16:30:01 -04005633 }
5634
5635 @Test
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005636 public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
5637 // Bubbles are allowed!
Mady Mellorc6820342019-05-20 12:04:36 -07005638 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005639
5640 // Plain notification that has bubble metadata
5641 NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
5642 null /* tvExtender */, true /* isBubble */);
Julia Reynoldsb6c83742019-07-30 18:03:40 -04005643 mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005644 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5645 waitForIdle();
5646
5647 // Would be a normal notification because wouldn't have met requirements to bubble
5648 StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
5649 assertEquals(1, notifsBefore.length);
5650 assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
5651
5652 // Make the package foreground so that we're allowed to be a bubble
5653 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5654 IMPORTANCE_FOREGROUND);
5655
5656 // And we are low ram
5657 when(mActivityManager.isLowRamDevice()).thenReturn(true);
5658
5659 // We wouldn't be a bubble because the notification didn't meet requirements (low ram)
5660 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5661 assertEquals(1, notifsAfter.length);
5662 assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
Mady Mellor5c11a2e2019-04-25 17:26:15 -07005663 }
Julia Reynoldsb681ffe2019-06-19 13:40:46 -04005664
5665 @Test
5666 public void testRemoveLargeRemoteViews() throws Exception {
5667 int removeSize = mContext.getResources().getInteger(
5668 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
5669
5670 RemoteViews rv = mock(RemoteViews.class);
5671 when(rv.estimateMemoryUsage()).thenReturn(removeSize);
5672 when(rv.clone()).thenReturn(rv);
5673 RemoteViews rv1 = mock(RemoteViews.class);
5674 when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
5675 when(rv1.clone()).thenReturn(rv1);
5676 RemoteViews rv2 = mock(RemoteViews.class);
5677 when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
5678 when(rv2.clone()).thenReturn(rv2);
5679 RemoteViews rv3 = mock(RemoteViews.class);
5680 when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
5681 when(rv3.clone()).thenReturn(rv3);
5682 RemoteViews rv4 = mock(RemoteViews.class);
5683 when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
5684 when(rv4.clone()).thenReturn(rv4);
5685 // note: different!
5686 RemoteViews rv5 = mock(RemoteViews.class);
5687 when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
5688 when(rv5.clone()).thenReturn(rv5);
5689
5690 Notification np = new Notification.Builder(mContext, "test")
5691 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5692 .setContentText("test")
5693 .setCustomContentView(rv)
5694 .setCustomBigContentView(rv1)
5695 .setCustomHeadsUpContentView(rv2)
5696 .build();
5697 Notification n = new Notification.Builder(mContext, "test")
5698 .setSmallIcon(android.R.drawable.sym_def_app_icon)
5699 .setContentText("test")
5700 .setCustomContentView(rv3)
5701 .setCustomBigContentView(rv4)
5702 .setCustomHeadsUpContentView(rv5)
5703 .setPublicVersion(np)
5704 .build();
5705
5706 assertNotNull(np.contentView);
5707 assertNotNull(np.bigContentView);
5708 assertNotNull(np.headsUpContentView);
5709
5710 assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
5711 assertNotNull(n.publicVersion.contentView);
5712 assertNotNull(n.publicVersion.bigContentView);
5713 assertNotNull(n.publicVersion.headsUpContentView);
5714
5715 mService.fixNotification(n, PKG, "tag", 9, 0);
5716
5717 assertNull(n.contentView);
5718 assertNull(n.bigContentView);
5719 assertNotNull(n.headsUpContentView);
5720 assertNull(n.publicVersion.contentView);
5721 assertNull(n.publicVersion.bigContentView);
5722 assertNull(n.publicVersion.headsUpContentView);
5723
5724 verify(mUsageStats, times(5)).registerImageRemoved(PKG);
5725 }
Mady Mellor06b770c2019-08-29 18:01:00 -07005726
Mady Mellora7731962019-06-17 17:57:02 -07005727 public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
5728 throws Exception {
5729 // Bubbles are allowed!
5730 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5731
5732 // Give it bubble metadata
5733 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5734 .setSuppressNotification(true)
5735 .setAutoExpandBubble(true).build();
5736 // Give it a person
5737 Person person = new Person.Builder()
5738 .setName("bubblebot")
5739 .build();
5740 // It needs remote input to be bubble-able
5741 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5742 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5743 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5744 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5745 inputIntent).addRemoteInput(remoteInput)
5746 .build();
5747 // Make it messaging style
5748 Notification.Builder nb = new Notification.Builder(mContext,
5749 mTestNotificationChannel.getId())
5750 .setContentTitle("foo")
5751 .setBubbleMetadata(data)
5752 .setStyle(new Notification.MessagingStyle(person)
5753 .setConversationTitle("Bubble Chat")
5754 .addMessage("Hello?",
5755 SystemClock.currentThreadTimeMillis() - 300000, person)
5756 .addMessage("Is it me you're looking for?",
5757 SystemClock.currentThreadTimeMillis(), person)
5758 )
5759 .setActions(replyAction)
5760 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5761
5762 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5763 nb.build(), new UserHandle(mUid), null, 0);
5764 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5765
5766 // Ensure we're not foreground
5767 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5768 IMPORTANCE_VISIBLE);
5769
5770 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5771 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5772 waitForIdle();
5773
5774 // yes allowed, yes messaging, yes bubble
5775 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5776 assertTrue(notif.isBubbleNotification());
5777
5778 // Our flags should have failed since we're not foreground
5779 assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
5780 assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
5781 }
5782
5783 @Test
5784 public void testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground()
5785 throws RemoteException {
5786 // Bubbles are allowed!
5787 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5788
5789 // Give it bubble metadata
5790 Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder()
5791 .setSuppressNotification(true)
5792 .setAutoExpandBubble(true).build();
5793 // Give it a person
5794 Person person = new Person.Builder()
5795 .setName("bubblebot")
5796 .build();
5797 // It needs remote input to be bubble-able
5798 RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
5799 PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
5800 Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
5801 Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
5802 inputIntent).addRemoteInput(remoteInput)
5803 .build();
5804 // Make it messaging style
5805 Notification.Builder nb = new Notification.Builder(mContext,
5806 mTestNotificationChannel.getId())
5807 .setContentTitle("foo")
5808 .setBubbleMetadata(data)
5809 .setStyle(new Notification.MessagingStyle(person)
5810 .setConversationTitle("Bubble Chat")
5811 .addMessage("Hello?",
5812 SystemClock.currentThreadTimeMillis() - 300000, person)
5813 .addMessage("Is it me you're looking for?",
5814 SystemClock.currentThreadTimeMillis(), person)
5815 )
5816 .setActions(replyAction)
5817 .setSmallIcon(android.R.drawable.sym_def_app_icon);
5818
5819 StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
5820 nb.build(), new UserHandle(mUid), null, 0);
5821 NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
5822
5823 // Ensure we are in the foreground
5824 when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
5825 IMPORTANCE_FOREGROUND);
5826
5827 mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
5828 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
5829 waitForIdle();
5830
5831 // yes allowed, yes messaging, yes bubble
5832 Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification();
5833 assertTrue(notif.isBubbleNotification());
5834
5835 // Our flags should have failed since we are foreground
5836 assertTrue(notif.getBubbleMetadata().getAutoExpandBubble());
5837 assertTrue(notif.getBubbleMetadata().isNotificationSuppressed());
5838 }
Mady Mellor22f2f072019-04-18 13:26:18 -07005839
5840 @Test
5841 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryDismissed()
5842 throws Exception {
5843 // Bubbles are allowed!
5844 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5845
5846 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5847 true /* summaryAutoCancel */);
5848
5849 // Dismiss summary
5850 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5851 true);
5852 mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, nrSummary.sbn.getTag(),
5853 nrSummary.sbn.getId(), nrSummary.getUserId(), nrSummary.getKey(),
5854 NotificationStats.DISMISSAL_SHADE,
5855 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
5856 waitForIdle();
5857
5858 // The bubble should still exist
5859 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5860 assertEquals(1, notifsAfter.length);
5861 }
5862
5863 @Test
5864 public void testNotificationBubbles_bubbleChildrenStay_whenGroupSummaryClicked()
5865 throws Exception {
5866 // Bubbles are allowed!
5867 setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
5868
5869 NotificationRecord nrSummary = addGroupWithBubblesAndValidateAdded(
5870 true /* summaryAutoCancel */);
5871
5872 // Click summary
5873 final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
5874 true);
5875 mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
5876 nrSummary.getKey(), nv);
5877 waitForIdle();
5878
5879 // The bubble should still exist
5880 StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
5881 assertEquals(1, notifsAfter.length);
5882 }
Julia Reynolds57a974b2019-10-07 11:51:47 -04005883
5884 @Test
5885 public void testLoadDefaultApprovedServices_emptyResources() {
5886 TestableResources tr = mContext.getOrCreateTestableResources();
5887 tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
5888 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
5889 tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
5890 setDefaultAssistantInDeviceConfig("");
5891
5892 mService.loadDefaultApprovedServices(USER_SYSTEM);
5893
5894 verify(mListeners, never()).addDefaultComponentOrPackage(anyString());
5895 verify(mConditionProviders, never()).addDefaultComponentOrPackage(anyString());
5896 verify(mAssistants, never()).addDefaultComponentOrPackage(anyString());
5897 }
5898
5899 @Test
5900 public void testLoadDefaultApprovedServices_dnd() {
5901 TestableResources tr = mContext.getOrCreateTestableResources();
5902 tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "test");
5903 when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
5904 .thenReturn(new ArraySet<>());
5905
5906 mService.loadDefaultApprovedServices(USER_SYSTEM);
5907
5908 verify(mConditionProviders, times(1)).addDefaultComponentOrPackage("test");
5909 }
5910
5911 // TODO: add tests for the rest of the non-empty cases
Geoffrey Pitsche75a66e2016-11-22 11:12:11 -05005912}