From 339b79f5d24f2d373328ba13e8bacd1b8078e9cb Mon Sep 17 00:00:00 2001 From: Mehdi Alizadeh Date: Sat, 1 Aug 2020 22:46:27 -0700 Subject: [PATCH] Fixes the incorrect component enabled check in ShortcutService ag/10755817 checks the enabled state of activities, but due to b/38267327, ActivityInfo.enabled may not reflect the current state of the component if the enabled state is changed after app is installed, which was the root cause of cts failures. This CL checks the enabled state via PackageManager.getComponentEnabledSetting, to cover such cases. Bug: 161657919 Test: atest CtsShortcutHostTestCases Test: atest CtsShortcutManagerTestCases Change-Id: Ide998a0fbc2c1e9fe1e77daeecc3a8c98d0425ab --- .../android/server/pm/ShortcutService.java | 72 ++++++++++++------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 89ed3c7557834..700f7be83e156 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -260,7 +260,8 @@ public class ShortcutService extends IShortcutService.Stub { private static final int PACKAGE_MATCH_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.MATCH_UNINSTALLED_PACKAGES; + | PackageManager.MATCH_UNINSTALLED_PACKAGES + | PackageManager.MATCH_DISABLED_COMPONENTS; private static final int SYSTEM_APP_MASK = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; @@ -278,12 +279,6 @@ public class ShortcutService extends IShortcutService.Stub { } }; - private static Predicate ACTIVITY_NOT_SYSTEM_NOR_ENABLED = (ri) -> { - final ApplicationInfo ai = ri.activityInfo.applicationInfo; - final boolean isSystemApp = ai != null && (ai.flags & SYSTEM_APP_MASK) != 0; - return !isSystemApp && !ri.activityInfo.enabled; - }; - private static Predicate ACTIVITY_NOT_INSTALLED = (ri) -> !isInstalled(ri.activityInfo); @@ -3685,10 +3680,8 @@ public class ShortcutService extends IShortcutService.Stub { final long start = getStatStartTime(); final long token = injectClearCallingIdentity(); try { - return mIPackageManager.getPackageInfo( - packageName, PACKAGE_MATCH_FLAGS | PackageManager.MATCH_DISABLED_COMPONENTS - | (getSignatures ? PackageManager.GET_SIGNING_CERTIFICATES : 0), - userId); + return mIPackageManager.getPackageInfo(packageName, PACKAGE_MATCH_FLAGS + | (getSignatures ? PackageManager.GET_SIGNING_CERTIFICATES : 0), userId); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, "RemoteException", e); @@ -3721,8 +3714,7 @@ public class ShortcutService extends IShortcutService.Stub { final long start = getStatStartTime(); final long token = injectClearCallingIdentity(); try { - return mIPackageManager.getApplicationInfo(packageName, - PACKAGE_MATCH_FLAGS | PackageManager.MATCH_DISABLED_COMPONENTS, userId); + return mIPackageManager.getApplicationInfo(packageName, PACKAGE_MATCH_FLAGS, userId); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, "RemoteException", e); @@ -3753,9 +3745,8 @@ public class ShortcutService extends IShortcutService.Stub { final long start = getStatStartTime(); final long token = injectClearCallingIdentity(); try { - return mIPackageManager.getActivityInfo(activity, (PACKAGE_MATCH_FLAGS - | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_META_DATA), - userId); + return mIPackageManager.getActivityInfo(activity, + PACKAGE_MATCH_FLAGS | PackageManager.GET_META_DATA, userId); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, "RemoteException", e); @@ -3800,8 +3791,7 @@ public class ShortcutService extends IShortcutService.Stub { List injectGetPackagesWithUninstalled(@UserIdInt int userId) throws RemoteException { final ParceledListSlice parceledList = - mIPackageManager.getInstalledPackages( - PACKAGE_MATCH_FLAGS | PackageManager.MATCH_DISABLED_COMPONENTS, userId); + mIPackageManager.getInstalledPackages(PACKAGE_MATCH_FLAGS, userId); if (parceledList == null) { return Collections.emptyList(); } @@ -3836,6 +3826,41 @@ public class ShortcutService extends IShortcutService.Stub { return (ai != null) && ((ai.flags & flags) == flags); } + // Due to b/38267327, ActivityInfo.enabled may not reflect the current state of the component + // and we need to check the enabled state via PackageManager.getComponentEnabledSetting. + private boolean isEnabled(@Nullable ActivityInfo ai, int userId) { + if (ai == null) { + return false; + } + + int enabledFlag; + final long token = injectClearCallingIdentity(); + try { + enabledFlag = mIPackageManager.getComponentEnabledSetting( + ai.getComponentName(), userId); + } catch (RemoteException e) { + // Shouldn't happen. + Slog.wtf(TAG, "RemoteException", e); + return false; + } finally { + injectRestoreCallingIdentity(token); + } + + if ((enabledFlag == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT && ai.enabled) + || enabledFlag == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { + return true; + } + return false; + } + + private static boolean isSystem(@Nullable ActivityInfo ai) { + return (ai != null) && isSystem(ai.applicationInfo); + } + + private static boolean isSystem(@Nullable ApplicationInfo ai) { + return (ai != null) && (ai.flags & SYSTEM_APP_MASK) != 0; + } + private static boolean isInstalled(@Nullable ApplicationInfo ai) { return (ai != null) && ai.enabled && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0; } @@ -3900,12 +3925,6 @@ public class ShortcutService extends IShortcutService.Stub { return intent; } - private static boolean isSystemApp(@Nullable final ApplicationInfo ai) { - final int systemAppMask = - ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; - return ai != null && ((ai.flags & systemAppMask) != 0); - } - /** * Same as queryIntentActivitiesAsUser, except it makes sure the package is installed, * and only returns exported activities. @@ -3938,7 +3957,10 @@ public class ShortcutService extends IShortcutService.Stub { } // Make sure the package is installed. resolved.removeIf(ACTIVITY_NOT_INSTALLED); - resolved.removeIf(ACTIVITY_NOT_SYSTEM_NOR_ENABLED); + resolved.removeIf((ri) -> { + final ActivityInfo ai = ri.activityInfo; + return !isSystem(ai) && !isEnabled(ai, userId); + }); if (exportedOnly) { resolved.removeIf(ACTIVITY_NOT_EXPORTED); }