diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index ae709feb4bd3e..56d679ef4fa40 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -1529,10 +1529,11 @@ public class ShortcutService extends IShortcutService.Stub { if (UserHandle.getUserId(callingUid) != userId) { throw new SecurityException("Invalid user-ID"); } - if (injectGetPackageUid(packageName, userId) == callingUid) { - return; // Caller is valid. + if (injectGetPackageUid(packageName, userId) != callingUid) { + throw new SecurityException("Calling package name mismatch"); } - throw new SecurityException("Calling package name mismatch"); + Preconditions.checkState(!isEphemeralApp(packageName, userId), + "Ephemeral apps can't use ShortcutManager"); } // Overridden in unit tests to execute r synchronously. @@ -3073,6 +3074,10 @@ public class ShortcutService extends IShortcutService.Stub { return (ai != null) && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0; } + private static boolean isEphemeralApp(@Nullable ApplicationInfo ai) { + return (ai != null) && ai.isEphemeralApp(); + } + private static boolean isInstalled(@Nullable PackageInfo pi) { return (pi != null) && isInstalled(pi.applicationInfo); } @@ -3097,6 +3102,10 @@ public class ShortcutService extends IShortcutService.Stub { return getApplicationInfo(packageName, userId) != null; } + boolean isEphemeralApp(String packageName, int userId) { + return isEphemeralApp(getApplicationInfo(packageName, userId)); + } + @Nullable XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) { return activityInfo.loadXmlMetaData(mContext.getPackageManager(), key); 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 167b33ac31a79..9835c88c98c28 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -566,6 +566,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected Map mInjectedPackages; protected Set mUninstalledPackages; + protected Set mEphemeralPackages; protected Set mSystemPackages; protected PackageManager mMockPackageManager; @@ -731,6 +732,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { mUninstalledPackages = new HashSet<>(); mSystemPackages = new HashSet<>(); + mEphemeralPackages = new HashSet<>(); mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files"); @@ -1034,6 +1036,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) { ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; } + if (mEphemeralPackages.contains(PackageWithUser.of(userId, packageName))) { + ret.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL; + } if (mSystemPackages.contains(packageName)) { ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; } diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index d25923c019cac..562de4148bb1e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -46,6 +46,7 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.frameworks.servicestests.R; import com.android.server.pm.ShortcutService.ConfigConstants; +import com.android.server.pm.ShortcutUser.PackageWithUser; import java.io.File; import java.io.FileWriter; @@ -2037,4 +2038,32 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertFalse(mService.isUserUnlockedL(USER_0)); assertFalse(mService.isUserUnlockedL(USER_10)); } + + public void testEphemeralApp() { + mRunningUsers.put(USER_10, true); // this test needs user 10. + + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertWith(mManager.getDynamicShortcuts()).isEmpty(); + }); + runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { + assertWith(mManager.getDynamicShortcuts()).isEmpty(); + }); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertWith(mManager.getDynamicShortcuts()).isEmpty(); + }); + // Make package 1 ephemeral. + mEphemeralPackages.add(PackageWithUser.of(USER_0, CALLING_PACKAGE_1)); + + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertExpectException(IllegalStateException.class, "Ephemeral apps", () -> { + mManager.getDynamicShortcuts(); + }); + }); + runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { + assertWith(mManager.getDynamicShortcuts()).isEmpty(); + }); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertWith(mManager.getDynamicShortcuts()).isEmpty(); + }); + } }