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

Commit fd7adede authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add new disabled state for "optional" built-in apps.

The disabled state allows you to make an app disabled
except for whatever parts of the system still want to
provide access to them and automatically enable them
if the user want to use it.

Currently the input method manager service is the only
part of the system that supports this, so you can put
an IME in this state and it will generally look disabled
but still be available in the IME list and once selected
switched to the enabled state.

Change-Id: I77f01c70610d82ce9070d4aabbadec8ae2cff2a3
parent cc743347
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6627,6 +6627,7 @@ package android.content.pm {
    method public abstract void verifyPendingInstall(int, int);
    field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
    field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
    field public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; // 0x4
    field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
    field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
    field public static final int DONT_KILL_APP = 1; // 0x1
@@ -6673,6 +6674,7 @@ package android.content.pm {
    field public static final int GET_ACTIVITIES = 1; // 0x1
    field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
    field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
    field public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
    field public static final int GET_GIDS = 256; // 0x100
    field public static final int GET_INSTRUMENTATION = 16; // 0x10
    field public static final int GET_INTENT_FILTERS = 32; // 0x20
+8 −0
Original line number Diff line number Diff line
@@ -135,6 +135,11 @@ public final class Pm {
            return;
        }

        if ("disable-until-used".equals(op)) {
            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
            return;
        }

        if ("grant".equals(op)) {
            runGrantRevokePermission(true);
            return;
@@ -1178,6 +1183,8 @@ public final class Pm {
                return "disabled";
            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
                return "disabled-user";
            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
                return "disabled-until-used";
        }
        return "unknown";
    }
@@ -1459,6 +1466,7 @@ public final class Pm {
        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
        System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
        System.err.println("       pm grant PACKAGE PERMISSION");
        System.err.println("       pm revoke PACKAGE PERMISSION");
        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
+4 −2
Original line number Diff line number Diff line
@@ -1588,7 +1588,7 @@ public class Intent implements Parcelable, Cloneable {
     * <ul>
     * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
     * <li> {@link #EXTRA_CHANGED_COMPONENT_NAME_LIST} containing the class name
     * of the changed components.
     * of the changed components (or the package name itself).
     * <li> {@link #EXTRA_DONT_KILL_APP} containing boolean field to override the
     * default action of restarting the application.
     * </ul>
@@ -2969,7 +2969,9 @@ public class Intent implements Parcelable, Cloneable {

    /**
     * This field is part of {@link android.content.Intent#ACTION_PACKAGE_CHANGED},
     * and contains a string array of all of the components that have changed.
     * and contains a string array of all of the components that have changed.  If
     * the state of the overall package has changed, then it will contain an entry
     * with the package name itself.
     */
    public static final String EXTRA_CHANGED_COMPONENT_NAME_LIST =
            "android.intent.extra.changed_component_name_list";
+21 −0
Original line number Diff line number Diff line
@@ -174,6 +174,14 @@ public abstract class PackageManager {
     */
    public static final int GET_CONFIGURATIONS = 0x00004000;

    /**
     * {@link PackageInfo} flag: include disabled components which are in
     * that state only because of {@link #COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED}
     * in the returned info.  Note that if you set this flag, applications
     * that are in this disabled state will be reported as enabled.
     */
    public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 0x00008000;

    /**
     * Resolution and querying flag: if set, only filters that support the
     * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
@@ -264,6 +272,19 @@ public abstract class PackageManager {
     */
    public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;

    /**
     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: This
     * application should be considered, until the point where the user actually
     * wants to use it.  This means that it will not normally show up to the user
     * (such as in the launcher), but various parts of the user interface can
     * use {@link #GET_DISABLED_UNTIL_USED_COMPONENTS} to still see it and allow
     * the user to select it (as for example an IME, device admin, etc).  Such code,
     * once the user has selected the app, should at that point also make it enabled.
     * This option currently <strong>can not</strong> be used with
     * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
     */
    public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;

    /**
     * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
     * indicate that this package should be installed as forward locked, i.e. only the app itself
+34 −32
Original line number Diff line number Diff line
@@ -3527,29 +3527,45 @@ public class PackageParser {
        return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
    }

    public static ApplicationInfo generateApplicationInfo(Package p, int flags,
            PackageUserState state, int userId) {
        if (p == null) return null;
        if (!checkUseInstalled(flags, state)) {
            return null;
        }
        if (!copyNeeded(flags, p, state, null, userId)) {
            // CompatibilityMode is global state. It's safe to modify the instance
            // of the package.
    private static void updateApplicationInfo(ApplicationInfo ai, int flags,
            PackageUserState state) {
        // CompatibilityMode is global state.
        if (!sCompatibilityModeEnabled) {
                p.applicationInfo.disableCompatibilityMode();
            ai.disableCompatibilityMode();
        }
        if (state.installed) {
            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
        } else {
            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
        }
            // Make sure we report as installed.  Also safe to do, since the
            // default state should be installed (we will always copy if we
            // need to report it is not installed).
            p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
                p.applicationInfo.enabled = true;
            ai.enabled = true;
        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
            ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
                p.applicationInfo.enabled = false;
            ai.enabled = false;
        }
            p.applicationInfo.enabledSetting = state.enabled;
        ai.enabledSetting = state.enabled;
    }

    public static ApplicationInfo generateApplicationInfo(Package p, int flags,
            PackageUserState state, int userId) {
        if (p == null) return null;
        if (!checkUseInstalled(flags, state)) {
            return null;
        }
        if (!copyNeeded(flags, p, state, null, userId)
                && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
                        || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
            // In this case it is safe to directly modify the internal ApplicationInfo state:
            // - CompatibilityMode is global state, so will be the same for every call.
            // - We only come in to here if the app should reported as installed; this is the
            // default state, and we will do a copy otherwise.
            // - The enable state will always be reported the same for the application across
            // calls; the only exception is for the UNTIL_USED mode, and in that case we will
            // be doing a copy.
            updateApplicationInfo(p.applicationInfo, flags, state);
            return p.applicationInfo;
        }

@@ -3565,26 +3581,12 @@ public class PackageParser {
        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
            ai.sharedLibraryFiles = p.usesLibraryFiles;
        }
        if (!sCompatibilityModeEnabled) {
            ai.disableCompatibilityMode();
        }
        if (state.stopped) {
            ai.flags |= ApplicationInfo.FLAG_STOPPED;
        } else {
            ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
        }
        if (state.installed) {
            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
        } else {
            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
        }
        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
            ai.enabled = true;
        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
            ai.enabled = false;
        }
        ai.enabledSetting = state.enabled;
        updateApplicationInfo(ai, flags, state);
        return ai;
    }

Loading