Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d1fd8d0 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Secure MATCH_UNINSTALLED_PACKAGES across users

Introduce a new internal flag MATCH_ANY_USER for genuine uses
of searching through all apps on the device.

Some temporary accommodations for Launchers that reach across
to the work profile until we have a new LauncherApps API to do
that officially.

Bug: 31000380
Test: CTS tests added
Change-Id: I2e43dc49d6c2e11814a8f8d1eb07ef557f31af34
parent c1e6a12a
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ public class LauncherActivityInfo {
     * @return The label for the activity.
     */
    public CharSequence getLabel() {
        // TODO: Go through LauncherAppsService
        return mActivityInfo.loadLabel(mPm);
    }

@@ -101,6 +102,7 @@ public class LauncherActivityInfo {
     * @return The drawable associated with the activity.
     */
    public Drawable getIcon(int density) {
        // TODO: Go through LauncherAppsService
        final int iconRes = mActivityInfo.getIconResource();
        Drawable icon = null;
        // Get the preferred density icon from the app's resources
@@ -144,8 +146,9 @@ public class LauncherActivityInfo {
     */
    public long getFirstInstallTime() {
        try {
            // TODO: Go through LauncherAppsService
            return mPm.getPackageInfo(mActivityInfo.packageName,
                    PackageManager.GET_UNINSTALLED_PACKAGES).firstInstallTime;
                    PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime;
        } catch (NameNotFoundException nnfe) {
            // Sorry, can't find package
            return 0;
@@ -171,6 +174,7 @@ public class LauncherActivityInfo {
        Drawable originalIcon = getIcon(density);

        if (originalIcon instanceof BitmapDrawable) {
            // TODO: Go through LauncherAppsService
            return mPm.getUserBadgedIcon(originalIcon, mUser);
        } else {
            Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
+2 −2
Original line number Diff line number Diff line
@@ -447,12 +447,12 @@ public class LauncherApps {
    /**
     * Retrieve all of the information we know about a particular package / application.
     *
     * @param packageName The package of the application
     * @param packageName The package name of the application
     * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
     * @param user The UserHandle of the profile.
     *
     * @return An {@link ApplicationInfo} containing information about the package or
     *         null of the package isn't found.
     *         null if the package isn't installed for the given user.
     * @hide
     */
    public ApplicationInfo getApplicationInfo(String packageName, @ApplicationInfoFlags int flags,
+14 −0
Original line number Diff line number Diff line
@@ -434,6 +434,20 @@ public abstract class PackageManager {
     */
    public static final int MATCH_FACTORY_ONLY = 0x00200000;

    /**
     * Allows querying of packages installed for any user, not just the specific one. This flag
     * is only meant for use by apps that have INTERACT_ACROSS_USERS_FULL permission.
     * @hide
     */
    public static final int MATCH_ANY_USER = 0x00400000;

    /**
     * Combination of MATCH_ANY_USER and MATCH_UNINSTALLED_PACKAGES to mean any known
     * package.
     * @hide
     */
    public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;

    /**
     * Internal flag used to indicate that a system component has done their
     * homework and verified that they correctly handle packages and components
+16 −11
Original line number Diff line number Diff line
@@ -478,20 +478,25 @@ public class PackageParser {
    /**
     * Returns true if the package is installed and not hidden, or if the caller
     * explicitly wanted all uninstalled and hidden packages as well.
     * @param appInfo The applicationInfo of the app being checked.
     */
    private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
        return (state.installed && !state.hidden)
                || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
    private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
            ApplicationInfo appInfo) {
        // If available for the target user, or trying to match uninstalled packages and it's
        // a system app.
        return state.isAvailable(flags)
                || (appInfo != null && appInfo.isSystemApp()
                        && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
    }

    public static boolean isAvailable(PackageUserState state) {
        return checkUseInstalledOrHidden(0, state);
        return checkUseInstalledOrHidden(0, state, null);
    }

    public static PackageInfo generatePackageInfo(PackageParser.Package p,
            int gids[], int flags, long firstInstallTime, long lastUpdateTime,
            Set<String> grantedPermissions, PackageUserState state, int userId) {
        if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
        if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
            return null;
        }
        PackageInfo pi = new PackageInfo();
@@ -5445,7 +5450,7 @@ public class PackageParser {
    public static ApplicationInfo generateApplicationInfo(Package p, int flags,
            PackageUserState state, int userId) {
        if (p == null) return null;
        if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
        if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
            return null;
        }
        if (!copyNeeded(flags, p, state, null, userId)
@@ -5483,7 +5488,7 @@ public class PackageParser {
    public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
            PackageUserState state, int userId) {
        if (ai == null) return null;
        if (!checkUseInstalledOrHidden(flags, state)) {
        if (!checkUseInstalledOrHidden(flags, state, ai)) {
            return null;
        }
        // This is only used to return the ResolverActivity; we will just always
@@ -5549,7 +5554,7 @@ public class PackageParser {
    public static final ActivityInfo generateActivityInfo(Activity a, int flags,
            PackageUserState state, int userId) {
        if (a == null) return null;
        if (!checkUseInstalledOrHidden(flags, state)) {
        if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
            return null;
        }
        if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
@@ -5565,7 +5570,7 @@ public class PackageParser {
    public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
            PackageUserState state, int userId) {
        if (ai == null) return null;
        if (!checkUseInstalledOrHidden(flags, state)) {
        if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
            return null;
        }
        // This is only used to return the ResolverActivity; we will just always
@@ -5603,7 +5608,7 @@ public class PackageParser {
    public static final ServiceInfo generateServiceInfo(Service s, int flags,
            PackageUserState state, int userId) {
        if (s == null) return null;
        if (!checkUseInstalledOrHidden(flags, state)) {
        if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
            return null;
        }
        if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
@@ -5652,7 +5657,7 @@ public class PackageParser {
    public static final ProviderInfo generateProviderInfo(Provider p, int flags,
            PackageUserState state, int userId) {
        if (p == null) return null;
        if (!checkUseInstalledOrHidden(flags, state)) {
        if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
            return null;
        }
        if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
+13 −6
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;

import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

/**
@@ -80,9 +79,14 @@ public class PackageUserState {
    /**
     * Test if this package is installed.
     */
    public boolean isInstalled(int flags) {
        return (this.installed && !this.hidden)
                || (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
    public boolean isAvailable(int flags) {
        // True if it is installed for this user and it is not hidden. If it is hidden,
        // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
        final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
        final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
        return matchAnyUser
                || (this.installed
                        && (!this.hidden || matchUninstalled));
    }

    /**
@@ -95,11 +99,14 @@ public class PackageUserState {
     * </p>
     */
    public boolean isMatch(ComponentInfo componentInfo, int flags) {
        if (!isInstalled(flags)) return false;
        final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp();
        final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
        if (!isAvailable(flags)
                && !(isSystemApp && matchUninstalled)) return false;
        if (!isEnabled(componentInfo, flags)) return false;

        if ((flags & MATCH_SYSTEM_ONLY) != 0) {
            if (!componentInfo.applicationInfo.isSystemApp()) {
            if (!isSystemApp) {
                return false;
            }
        }
Loading