Fix crash in NotificationManager when WP is off
Shortcuts will crash if queried when locked. Early opt-out any calls into
LauncherApps when the user is locked.
Bug: 182575662
Test: NotificationManagerServiceTest, ShortcutHelperTest
Change-Id: Icf1c9fb09f3d1732f6d40b75412f833d7952f5d6
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5b5d5d4..b26485b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2661,8 +2661,10 @@
mRoleObserver = roleObserver;
LauncherApps launcherApps =
(LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE);
+ UserManager userManager = (UserManager) getContext().getSystemService(
+ Context.USER_SERVICE);
mShortcutHelper = new ShortcutHelper(launcherApps, mShortcutListener, getLocalService(
- ShortcutServiceInternal.class));
+ ShortcutServiceInternal.class), userManager);
BubbleExtractor bubbsExtractor = mRankingHelper.findExtractor(BubbleExtractor.class);
if (bubbsExtractor != null) {
bubbsExtractor.setShortcutHelper(mShortcutHelper);
diff --git a/services/core/java/com/android/server/notification/ShortcutHelper.java b/services/core/java/com/android/server/notification/ShortcutHelper.java
index b0be206..fc106b8 100644
--- a/services/core/java/com/android/server/notification/ShortcutHelper.java
+++ b/services/core/java/com/android/server/notification/ShortcutHelper.java
@@ -29,6 +29,7 @@
import android.os.Binder;
import android.os.Handler;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -67,6 +68,7 @@
private LauncherApps mLauncherAppsService;
private ShortcutListener mShortcutListener;
private ShortcutServiceInternal mShortcutServiceInternal;
+ private UserManager mUserManager;
// Key: packageName Value: <shortcutId, notifId>
private HashMap<String, HashMap<String, String>> mActiveShortcutBubbles = new HashMap<>();
@@ -144,10 +146,11 @@
};
ShortcutHelper(LauncherApps launcherApps, ShortcutListener listener,
- ShortcutServiceInternal shortcutServiceInternal) {
+ ShortcutServiceInternal shortcutServiceInternal, UserManager userManager) {
mLauncherAppsService = launcherApps;
mShortcutListener = listener;
mShortcutServiceInternal = shortcutServiceInternal;
+ mUserManager = userManager;
}
@VisibleForTesting
@@ -160,6 +163,11 @@
mShortcutServiceInternal = shortcutServiceInternal;
}
+ @VisibleForTesting
+ void setUserManager(UserManager userManager) {
+ mUserManager = userManager;
+ }
+
/**
* Returns whether the given shortcut info is a conversation shortcut.
*/
@@ -182,7 +190,8 @@
* Only returns shortcut info if it's found and if it's a conversation shortcut.
*/
ShortcutInfo getValidShortcutInfo(String shortcutId, String packageName, UserHandle user) {
- if (mLauncherAppsService == null) {
+ // Shortcuts cannot be accessed when the user is locked.
+ if (mLauncherAppsService == null || !mUserManager.isUserUnlocked(user)) {
return null;
}
final long token = Binder.clearCallingIdentity();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 2c7c3e3..70ba2cf 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -65,6 +65,8 @@
import static com.android.server.notification.NotificationManagerService.ACTION_ENABLE_NAS;
import static com.android.server.notification.NotificationManagerService.ACTION_LEARNMORE_NAS;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -261,6 +263,8 @@
@Mock
private ShortcutServiceInternal mShortcutServiceInternal;
@Mock
+ private UserManager mUserManager;
+ @Mock
ActivityManager mActivityManager;
@Mock
Resources mResources;
@@ -526,6 +530,7 @@
mShortcutHelper = mService.getShortcutHelper();
mShortcutHelper.setLauncherApps(mLauncherApps);
mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
+ mShortcutHelper.setUserManager(mUserManager);
// Capture PackageIntentReceiver
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
@@ -567,6 +572,7 @@
when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcutInfos);
when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
anyString(), anyInt(), any())).thenReturn(true);
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
// Set the testable bubble extractor
RankingHelper rankingHelper = mService.getRankingHelper();
@@ -7506,6 +7512,13 @@
mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
assertEquals(si, conversations.get(0).getShortcutInfo());
assertEquals(si, conversations.get(1).getShortcutInfo());
+
+ // Returns null shortcuts when locked.
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false);
+ conversations =
+ mBinderService.getConversationsForPackage(PKG_P, mUid).getList();
+ assertThat(conversations.get(0).getShortcutInfo()).isNull();
+ assertThat(conversations.get(1).getShortcutInfo()).isNull();
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
index f43e5a8..11cb150 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
@@ -34,6 +34,7 @@
import android.content.pm.ShortcutQueryWrapper;
import android.content.pm.ShortcutServiceInternal;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
@@ -71,6 +72,8 @@
@Mock
ShortcutHelper.ShortcutListener mShortcutListener;
@Mock
+ UserManager mUserManager;
+ @Mock
ShortcutServiceInternal mShortcutServiceInternal;
@Mock
NotificationRecord mNr;
@@ -92,11 +95,12 @@
MockitoAnnotations.initMocks(this);
mShortcutHelper = new ShortcutHelper(
- mLauncherApps, mShortcutListener, mShortcutServiceInternal);
+ mLauncherApps, mShortcutListener, mShortcutServiceInternal, mUserManager);
when(mSbn.getPackageName()).thenReturn(PKG);
when(mShortcutInfo.getId()).thenReturn(SHORTCUT_ID);
when(mNotif.getBubbleMetadata()).thenReturn(mBubbleMetadata);
when(mBubbleMetadata.getShortcutId()).thenReturn(SHORTCUT_ID);
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
setUpMockNotificationRecord(mNr, KEY);
}
@@ -317,6 +321,25 @@
.isSameInstanceAs(si);
}
+
+ @Test
+ public void testGetValidShortcutInfo_isValidButUserLocked() {
+ ShortcutInfo si = mock(ShortcutInfo.class);
+ when(si.getPackage()).thenReturn(PKG);
+ when(si.getId()).thenReturn(SHORTCUT_ID);
+ when(si.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
+ when(si.isLongLived()).thenReturn(true);
+ when(si.isEnabled()).thenReturn(true);
+ when(si.getPersons()).thenReturn(new Person[]{PERSON});
+ ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ shortcuts.add(si);
+ when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcuts);
+ when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(false);
+
+ assertThat(mShortcutHelper.getValidShortcutInfo("a", "p", UserHandle.SYSTEM))
+ .isNull();
+ }
+
@Test
public void testGetValidShortcutInfo_hasGetPersonsDataFlag() {