summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2017-11-06 16:26:32 -0800
committer Makoto Onuki <omakoto@google.com> 2017-11-08 15:52:23 -0800
commit35559d6125045a38a01ba30a32f7ca36abfeebac (patch)
tree5ddbf341e10cb1c2ffc87040bbe4e7f6bbea8de2
parenta7d81598b5cd7c12e97f64015c9f5e316eadaf13 (diff)
Allow assistant app to access any shortcuts
Bug: 68760723 Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest1 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest2 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest3 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest4 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest5 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest6 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest7 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest8 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest9 -w com.android.frameworks.servicestests Test: adb shell am instrument -w -e class com.android.server.pm.ShortcutManagerTest10 -w com.android.frameworks.servicestests Test: cts-tradefed run cts-dev --skip-device-info --skip-preconditions --skip-system-status-check com.android.compatibility.common.tradefed.targetprep.NetworkConnectivityChecker -a armeabi-v7a -l INFO -m CtsShortcutManagerTestCases Change-Id: I8c0f0ba1f01c1da7df44bb235abdaa94c36d86d3
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt2
-rw-r--r--core/java/android/content/pm/LauncherApps.java12
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java10
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java37
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java64
8 files changed, 104 insertions, 26 deletions
diff --git a/api/current.txt b/api/current.txt
index 0eb47154638e..eea85b177a0c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10568,6 +10568,7 @@ package android.content.pm {
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
+ field public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1024; // 0x400
}
public class PackageInfo implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 1747f23785c4..2a7815451a5c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11186,6 +11186,7 @@ package android.content.pm {
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
+ field public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1024; // 0x400
}
public class PackageInfo implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 5664391d2c76..2428afdcdc59 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10647,10 +10647,10 @@ package android.content.pm {
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_ALL_PINNED = 1024; // 0x400
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
+ field public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1024; // 0x400
}
public class PackageInfo implements android.os.Parcelable {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 05c555685384..9e54e235325c 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -282,13 +282,13 @@ public class LauncherApps {
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
/**
- * @hide include all pinned shortcuts by any launchers, not just by the caller,
+ * Include all pinned shortcuts by any launchers, not just by the caller,
* in the result.
- * If the caller doesn't havve the {@link android.Manifest.permission#ACCESS_SHORTCUTS}
- * permission, this flag will be ignored.
+ *
+ * The caller must be the selected assistant app to use this flag, or have the system
+ * {@code ACCESS_SHORTCUTS} permission.
*/
- @TestApi
- public static final int FLAG_MATCH_ALL_PINNED = 1 << 10;
+ public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;
/**
* FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST
@@ -302,7 +302,7 @@ public class LauncherApps {
* @hide
*/
public static final int FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED =
- FLAG_MATCH_ALL_KINDS | FLAG_MATCH_ALL_PINNED;
+ FLAG_MATCH_ALL_KINDS | FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
/** @hide kept for unit tests */
@Deprecated
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index a3585bc1f97d..ba97c428bb44 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -615,10 +615,16 @@ class ShortcutPackage extends ShortcutPackageItem {
// Fix up isPinned for the caller. Note we need to do it before the "test" callback,
// since it may check isPinned.
- if (!isPinnedByCaller) {
- clone.clearFlags(ShortcutInfo.FLAG_PINNED);
+ // However, if getPinnedByAnyLauncher is set, we do it after the test.
+ if (!getPinnedByAnyLauncher) {
+ if (!isPinnedByCaller) {
+ clone.clearFlags(ShortcutInfo.FLAG_PINNED);
+ }
}
if (query == null || query.test(clone)) {
+ if (!isPinnedByCaller) {
+ clone.clearFlags(ShortcutInfo.FLAG_PINNED);
+ }
result.add(clone);
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 25e923994789..0907dd7c5a9e 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2234,7 +2234,7 @@ public class ShortcutService extends IShortcutService.Stub {
// We override this method in unit tests to do a simpler check.
boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId,
int callingPid, int callingUid) {
- if (injectCheckAccessShortcutsPermission(callingPid, callingUid)) {
+ if (canSeeAnyPinnedShortcut(callingPackage, userId, callingPid, callingUid)) {
return true;
}
final long start = injectElapsedRealtime();
@@ -2245,10 +2245,21 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ boolean canSeeAnyPinnedShortcut(@NonNull String callingPackage, int userId,
+ int callingPid, int callingUid) {
+ if (injectHasAccessShortcutsPermission(callingPid, callingUid)) {
+ return true;
+ }
+ synchronized (mLock) {
+ return getUserShortcutsLocked(userId).hasHostPackage(callingPackage);
+ }
+ }
+
/**
* Returns true if the caller has the "ACCESS_SHORTCUTS" permission.
*/
- boolean injectCheckAccessShortcutsPermission(int callingPid, int callingUid) {
+ @VisibleForTesting
+ boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
return mContext.checkPermission(android.Manifest.permission.ACCESS_SHORTCUTS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
}
@@ -2262,10 +2273,6 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutUser user = getUserShortcutsLocked(userId);
- if (user.hasHostPackage(packageName)) {
- return true;
- }
-
// Always trust the cached component.
final ComponentName cached = user.getCachedLauncher();
if (cached != null) {
@@ -2491,8 +2498,8 @@ public class ShortcutService extends IShortcutService.Stub {
final ArraySet<String> ids = shortcutIds == null ? null
: new ArraySet<>(shortcutIds);
- final ShortcutPackage p = getUserShortcutsLocked(userId)
- .getPackageShortcutsIfExists(packageName);
+ final ShortcutUser user = getUserShortcutsLocked(userId);
+ final ShortcutPackage p = user.getPackageShortcutsIfExists(packageName);
if (p == null) {
return; // No need to instantiate ShortcutPackage.
}
@@ -2500,9 +2507,12 @@ public class ShortcutService extends IShortcutService.Stub {
final boolean matchPinned = (queryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
final boolean matchManifest = (queryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
+ final boolean canAccessAllShortcuts =
+ canSeeAnyPinnedShortcut(callingPackage, launcherUserId, callingPid, callingUid);
+
final boolean getPinnedByAnyLauncher =
- ((queryFlags & ShortcutQuery.FLAG_MATCH_ALL_PINNED) != 0)
- && injectCheckAccessShortcutsPermission(callingPid, callingUid);
+ canAccessAllShortcuts &&
+ ((queryFlags & ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER) != 0);
p.findAll(ret,
(ShortcutInfo si) -> {
@@ -2521,7 +2531,7 @@ public class ShortcutService extends IShortcutService.Stub {
if (matchDynamic && si.isDynamic()) {
return true;
}
- if ((matchPinned && si.isPinned()) || getPinnedByAnyLauncher) {
+ if ((matchPinned || getPinnedByAnyLauncher) && si.isPinned()) {
return true;
}
if (matchManifest && si.isDeclaredInManifest()) {
@@ -2614,14 +2624,15 @@ public class ShortcutService extends IShortcutService.Stub {
.attemptToRestoreIfNeededAndSave();
final boolean getPinnedByAnyLauncher =
- injectCheckAccessShortcutsPermission(callingPid, callingUid);
+ canSeeAnyPinnedShortcut(callingPackage, launcherUserId,
+ callingPid, callingUid);
// Make sure the shortcut is actually visible to the launcher.
final ShortcutInfo si = getShortcutInfoLocked(
launcherUserId, callingPackage, packageName, shortcutId, userId,
getPinnedByAnyLauncher);
// "si == null" should suffice here, but check the flags too just to make sure.
- if (si == null || !si.isEnabled() || !si.isAlive()) {
+ if (si == null || !si.isEnabled() || !(si.isAlive() || getPinnedByAnyLauncher)) {
Log.e(TAG, "Shortcut " + shortcutId + " does not exist or disabled");
return null;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 6bb5bc6cd162..025ebc36f99b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -453,7 +453,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
- boolean injectCheckAccessShortcutsPermission(int callingPid, int callingUid) {
+ boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
return mInjectCheckAccessShortcutsPermission;
}
@@ -1648,7 +1648,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId,
int userId) {
assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId));
- assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId));
}
protected void assertShortcutNotLaunched(@NonNull String packageName,
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index b5e8e1ca046f..f92b575bc976 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1918,7 +1918,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Make sure FLAG_MATCH_ALL_PINNED will be ignored.
assertWith(mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
/* activity =*/ null, ShortcutQuery.FLAG_MATCH_PINNED
- | ShortcutQuery.FLAG_MATCH_ALL_PINNED), getCallingUser()))
+ | ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER), getCallingUser()))
.isEmpty();
// Make sure the special permission works.
@@ -1928,14 +1928,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertWith(mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
/* activity =*/ null, ShortcutQuery.FLAG_MATCH_PINNED
- | ShortcutQuery.FLAG_MATCH_ALL_PINNED), getCallingUser()))
+ | ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER), getCallingUser()))
.haveIds("s1", "s2");
assertWith(mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
/* activity =*/ null, ShortcutQuery.FLAG_MATCH_PINNED), getCallingUser()))
.isEmpty();
+ assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", getCallingUser().getIdentifier());
+
mInjectCheckAccessShortcutsPermission = false;
+ assertShortcutNotLaunched(CALLING_PACKAGE_2, "s1", getCallingUser().getIdentifier());
+
assertShortcutIds(assertAllDynamic(
mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
/* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
@@ -2106,6 +2110,62 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
+ public void testPinShortcutAndGetPinnedShortcuts_assistant() {
+ // Create some shortcuts.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+
+ // Pin some.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ list("s3", "s4"), getCallingUser());
+ });
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"))));
+ });
+
+ runWithCaller(LAUNCHER_2, USER_0, () -> {
+ final ShortcutQuery allPinned = new ShortcutQuery().setQueryFlags(
+ ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER);
+
+ assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+ .isEmpty();
+
+ assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+ assertShortcutNotLaunched(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunched(CALLING_PACKAGE_1, "s4", USER_0);
+
+ // Make it the assistant app.
+ mInternal.setShortcutHostPackage("assistant", LAUNCHER_2, USER_0);
+ assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+ .haveIds("s3");
+
+ assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+ assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunched(CALLING_PACKAGE_1, "s4", USER_0);
+
+ mInternal.setShortcutHostPackage("another-type", LAUNCHER_3, USER_0);
+ assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+ .haveIds("s3");
+
+ mInternal.setShortcutHostPackage("assistant", null, USER_0);
+ assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+ .isEmpty();
+
+ mInternal.setShortcutHostPackage("assistant", LAUNCHER_2, USER_0);
+ assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+ .haveIds("s3");
+
+ mInternal.setShortcutHostPackage("assistant", LAUNCHER_1, USER_0);
+ assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+ .isEmpty();
+ });
+ }
+
public void testPinShortcutAndGetPinnedShortcuts_crossProfile_plusLaunch() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {