ShortcutManaegr: bug fixes
Fixes 28590035
Fixes 28586105
Change-Id: Ia11d29e4996ad5b47b279a3c04d9586695cdc0a5
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 824722d..eaec1d7 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -243,7 +243,9 @@
}
/**
- * If non-null, returns only shortcuts associated with the activity.
+ * If non-null, returns only shortcuts associated with the activity, which are
+ * {@link ShortcutInfo}s that have null {@link ShortcutInfo#getActivityComponent()}, or
+ * {@link ShortcutInfo#getActivityComponent()} equals to {@code activity}.
*/
public void setActivity(@Nullable ComponentName activity) {
mActivity = activity;
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 0f17804..cf418b9 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1256,8 +1256,13 @@
}
private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
- if (!mUserManager.isUserRunning(userId)) {
- return;
+ final long token = injectClearCallingIdentity();
+ try {
+ if (!mUserManager.isUserRunning(userId)) {
+ return;
+ }
+ } finally {
+ injectRestoreCallingIdentity(token);
}
postToHandler(() -> {
final ArrayList<ShortcutChangeListener> copy;
@@ -1771,9 +1776,11 @@
if (ids != null && !ids.contains(si.getId())) {
return false;
}
- if (componentName != null
- && !componentName.equals(si.getActivityComponent())) {
- return false;
+ if (componentName != null) {
+ if (si.getActivityComponent() != null
+ && !si.getActivityComponent().equals(componentName)) {
+ return false;
+ }
}
final boolean matchDynamic =
((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index ced7cf0..b6ca4dd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -115,6 +115,8 @@
import org.junit.Assert;
import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -583,7 +585,7 @@
}).when(mMockUserManager).getUserInfo(eq(USER_P0));
// User 0 is always running.
- when(mMockUserManager.isUserRunning(eq(USER_0))).thenReturn(true);
+ when(mMockUserManager.isUserRunning(eq(USER_0))).thenAnswer(new AnswerIsUserRunning(true));
initService();
setCaller(CALLING_PACKAGE_1);
@@ -594,6 +596,24 @@
mInternal.onSystemLocaleChangedNoLock();
}
+ /**
+ * Returns a boolean but also checks if the current UID is SYSTEM_UID.
+ */
+ private class AnswerIsUserRunning implements Answer<Boolean> {
+ private final boolean mAnswer;
+
+ private AnswerIsUserRunning(boolean answer) {
+ mAnswer = answer;
+ }
+
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("isUserRunning() must be called on SYSTEM UID.",
+ Process.SYSTEM_UID, mInjectedCallingUid);
+ return mAnswer;
+ }
+ }
+
private static UserInfo withProfileGroupId(UserInfo in, int groupId) {
in.profileGroupId = groupId;
return in;
@@ -872,6 +892,18 @@
}
/**
+ * Make a shortcut with an ID, a timestamp and an activity component
+ */
+ private ShortcutInfo makeShortcutWithTimestampWithActivity(String id, long timestamp,
+ ComponentName activity) {
+ final ShortcutInfo s = makeShortcut(
+ id, "Title-" + id, activity, /* icon =*/ null,
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+ s.setTimestamp(timestamp);
+ return s;
+ }
+
+ /**
* Make a shortcut with an ID and icon.
*/
private ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
@@ -2014,8 +2046,10 @@
setCaller(CALLING_PACKAGE_2);
final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
- final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
- final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
+ final ShortcutInfo s2_3 = makeShortcutWithTimestampWithActivity("s3", 3000,
+ makeComponent(ShortcutActivity2.class));
+ final ShortcutInfo s2_4 = makeShortcutWithTimestampWithActivity("s4", 500,
+ makeComponent(ShortcutActivity.class));
assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
setCaller(CALLING_PACKAGE_3);
@@ -2056,6 +2090,15 @@
getCallingUser())),
"s2", "s3"))));
+ // Filter by activity
+ assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+ assertAllNotKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 0, CALLING_PACKAGE_2,
+ new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
+ ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC),
+ getCallingUser())),
+ "s2", "s4"))));
+
// With ID.
assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
@@ -2115,7 +2158,7 @@
/* activity =*/ null, /* flags */ 0), getCallingUser());
});
- // TODO More tests: pinned but dynamic, filter by activity
+ // TODO More tests: pinned but dynamic.
}
public void testGetShortcutInfo() {
@@ -3302,9 +3345,8 @@
assertCallbackNotReceived(c11_1);
// Work profile, now running.
-
- when(mMockUserManager.isUserRunning(anyInt())).thenReturn(false);
- when(mMockUserManager.isUserRunning(eq(USER_P0))).thenReturn(true);
+ doAnswer(new AnswerIsUserRunning(false)).when(mMockUserManager).isUserRunning(anyInt());
+ doAnswer(new AnswerIsUserRunning(true)).when(mMockUserManager).isUserRunning(eq(USER_P0));
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -3323,8 +3365,8 @@
// Normal secondary user.
- when(mMockUserManager.isUserRunning(anyInt())).thenReturn(false);
- when(mMockUserManager.isUserRunning(eq(USER_10))).thenReturn(true);
+ doAnswer(new AnswerIsUserRunning(false)).when(mMockUserManager).isUserRunning(anyInt());
+ doAnswer(new AnswerIsUserRunning(true)).when(mMockUserManager).isUserRunning(eq(USER_10));
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4377,7 +4419,7 @@
// notification to the launcher.
mInjectedCurrentTimeLillis = START_TIME + 200;
- when(mMockUserManager.isUserRunning(eq(USER_10))).thenReturn(true);
+ doAnswer(new AnswerIsUserRunning(true)).when(mMockUserManager).isUserRunning(eq(USER_10));
reset(c0);
reset(c10);