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

Commit db587c6e authored by Rhed Jao's avatar Rhed Jao
Browse files

Add multiple components support for component enabled setting updates

This cl creates a new API setComponentsEnabledSetting in PackageManager.
It accepts a list of component changes that applies them all atomically
in order to improve performance and minimize the risk of errors for the
applications.

Bug: 189883959
Test: atest PackageManagerTest
Change-Id: I64d9f46198e26e001e79ca9c198c26929adf8596
parent 5c18fc3e
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -12633,6 +12633,7 @@ package android.content.pm {
    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setApplicationEnabledSetting(@NonNull String, int, int);
    method @RequiresPermission(value="android.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS", conditional=true) public boolean setAutoRevokeWhitelisted(@NonNull String, boolean);
    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setComponentEnabledSetting(@NonNull android.content.ComponentName, int, int);
    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setComponentEnabledSettings(@NonNull java.util.List<android.content.pm.PackageManager.ComponentEnabledSetting>);
    method public abstract void setInstallerPackageName(@NonNull String, @Nullable String);
    method public void setMimeGroup(@NonNull String, @NonNull java.util.Set<java.lang.String>);
    method public abstract void updateInstantAppCookie(@Nullable byte[]);
@@ -12829,6 +12830,16 @@ package android.content.pm {
    field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
  }
  public static final class PackageManager.ComponentEnabledSetting implements android.os.Parcelable {
    ctor public PackageManager.ComponentEnabledSetting(@NonNull android.content.ComponentName, int, int);
    method public int describeContents();
    method @Nullable public android.content.ComponentName getComponentName();
    method public int getEnabledFlags();
    method public int getEnabledState();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageManager.ComponentEnabledSetting> CREATOR;
  }
  public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
    ctor public PackageManager.NameNotFoundException();
    ctor public PackageManager.NameNotFoundException(String);
+9 −0
Original line number Diff line number Diff line
@@ -2806,6 +2806,15 @@ public class ApplicationPackageManager extends PackageManager {
        }
    }

    @Override
    public void setComponentEnabledSettings(List<ComponentEnabledSetting> settings) {
        try {
            mPM.setComponentEnabledSettings(settings, getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public int getComponentEnabledSetting(ComponentName componentName) {
        try {
+6 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.content.pm.KeySet;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.ComponentEnabledSetting;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.PermissionGroupInfo;
@@ -358,6 +359,11 @@ interface IPackageManager {
    void setComponentEnabledSetting(in ComponentName componentName,
            in int newState, in int flags, int userId);

    /**
     * As per {@link android.content.pm.PackageManager#setComponentEnabledSettings}.
     */
    void setComponentEnabledSettings(in List<ComponentEnabledSetting> settings, int userId);

    /**
     * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
     */
+1 −0
Original line number Diff line number Diff line
@@ -18,3 +18,4 @@
package android.content.pm;

parcelable PackageManager.Property;
parcelable PackageManager.ComponentEnabledSetting;
+243 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ import android.util.Log;

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

import dalvik.system.VMRuntime;

@@ -379,6 +380,219 @@ public abstract class PackageManager {
        };
    }

    /**
     * The class containing the enabled setting of a package component.
     * <p>
     * This is used by the {@link #setComponentEnabledSettings(List)} to support the batch updates
     * of the enabled settings of components.
     *
     * @see #setComponentEnabledSettings(List)
     */
    @DataClass(genConstructor = false)
    public static final class ComponentEnabledSetting implements Parcelable {
        /**
         * The package name of the application to enable the setting.
         */
        private final @Nullable String mPackageName;

        /**
         * The component name of the application to enable the setting.
         */
        private final @Nullable ComponentName mComponentName;

        /**
         * The new enabled state
         */
        private final @EnabledState int mEnabledState;

        /**
         * The optional behavior flag
         */
        private final @EnabledFlags int mEnabledFlags;

        /**
         * Create an instance of the ComponentEnabledSetting for the component level's enabled
         * setting update.
         *
         * @param componentName The component name to update the enabled setting.
         * @param newState The new enabled state.
         * @param flags The optional behavior flags.
         */
        public ComponentEnabledSetting(@NonNull ComponentName componentName,
                @EnabledState int newState, @EnabledFlags int flags) {
            Objects.nonNull(componentName);
            mPackageName = null;
            mComponentName = componentName;
            mEnabledState = newState;
            mEnabledFlags = flags;
        }

        /**
         * Create an instance of the ComponentEnabledSetting for the application level's enabled
         * setting update.
         *
         * @param packageName The package name to update the enabled setting.
         * @param newState The new enabled state.
         * @param flags The optional behavior flags.
         * @hide
         */
        public ComponentEnabledSetting(@NonNull String packageName,
                @EnabledState int newState, @EnabledFlags int flags) {
            Objects.nonNull(packageName);
            mPackageName = packageName;
            mComponentName = null;
            mEnabledState = newState;
            mEnabledFlags = flags;
        }

        /**
         * Returns the package name of the setting.
         *
         * @return the package name.
         * @hide
         */
        public @NonNull String getPackageName() {
            if (isComponent()) {
                return mComponentName.getPackageName();
            }
            return mPackageName;
        }

        /**
         * Returns the component class name of the setting.
         *
         * @return the class name.
         * @hide
         */
        public @Nullable String getClassName() {
            if (isComponent()) {
                return mComponentName.getClassName();
            }
            return null;
        }

        /**
         * Whether or not this is for the component level's enabled setting update.
         *
         * @return {@code true} if it's the component level enabled setting update.
         * @hide
         */
        public boolean isComponent() {
            return mComponentName != null;
        }



        // Code below generated by codegen v1.0.23.
        //
        // DO NOT MODIFY!
        // CHECKSTYLE:OFF Generated code
        //
        // To regenerate run:
        // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageManager.java
        //
        // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
        //   Settings > Editor > Code Style > Formatter Control
        //@formatter:off


        /**
         * The component name of the application to enable the setting.
         */
        @DataClass.Generated.Member
        public @Nullable ComponentName getComponentName() {
            return mComponentName;
        }

        /**
         * The new enabled state
         */
        @DataClass.Generated.Member
        public @EnabledState int getEnabledState() {
            return mEnabledState;
        }

        /**
         * The optional behavior flag
         */
        @DataClass.Generated.Member
        public @EnabledFlags int getEnabledFlags() {
            return mEnabledFlags;
        }

        @Override
        @DataClass.Generated.Member
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            // You can override field parcelling by defining methods like:
            // void parcelFieldName(Parcel dest, int flags) { ... }

            byte flg = 0;
            if (mPackageName != null) flg |= 0x1;
            if (mComponentName != null) flg |= 0x2;
            dest.writeByte(flg);
            if (mPackageName != null) dest.writeString(mPackageName);
            if (mComponentName != null) dest.writeTypedObject(mComponentName, flags);
            dest.writeInt(mEnabledState);
            dest.writeInt(mEnabledFlags);
        }

        @Override
        @DataClass.Generated.Member
        public int describeContents() { return 0; }

        /** @hide */
        @SuppressWarnings({"unchecked", "RedundantCast"})
        @DataClass.Generated.Member
        /* package-private */ ComponentEnabledSetting(@NonNull Parcel in) {
            // You can override field unparcelling by defining methods like:
            // static FieldType unparcelFieldName(Parcel in) { ... }

            byte flg = in.readByte();
            String packageName = (flg & 0x1) == 0 ? null : in.readString();
            ComponentName componentName = (flg & 0x2) == 0 ? null : (ComponentName) in.readTypedObject(ComponentName.CREATOR);
            int enabledState = in.readInt();
            int enabledFlags = in.readInt();

            this.mPackageName = packageName;
            this.mComponentName = componentName;
            this.mEnabledState = enabledState;
            com.android.internal.util.AnnotationValidations.validate(
                    EnabledState.class, null, mEnabledState);
            this.mEnabledFlags = enabledFlags;
            com.android.internal.util.AnnotationValidations.validate(
                    EnabledFlags.class, null, mEnabledFlags);

            // onConstructed(); // You can define this method to get a callback
        }

        @DataClass.Generated.Member
        public static final @NonNull Parcelable.Creator<ComponentEnabledSetting> CREATOR
                = new Parcelable.Creator<ComponentEnabledSetting>() {
            @Override
            public ComponentEnabledSetting[] newArray(int size) {
                return new ComponentEnabledSetting[size];
            }

            @Override
            public ComponentEnabledSetting createFromParcel(@NonNull Parcel in) {
                return new ComponentEnabledSetting(in);
            }
        };

        @DataClass.Generated(
                time = 1628668290863L,
                codegenVersion = "1.0.23",
                sourceFile = "frameworks/base/core/java/android/content/pm/PackageManager.java",
                inputSignatures = "private final @android.annotation.Nullable java.lang.String mPackageName\nprivate final @android.annotation.Nullable android.content.ComponentName mComponentName\nprivate final @android.content.pm.PackageManager.EnabledState int mEnabledState\nprivate final @android.content.pm.PackageManager.EnabledFlags int mEnabledFlags\npublic @android.annotation.NonNull java.lang.String getPackageName()\npublic @android.annotation.Nullable java.lang.String getClassName()\npublic  boolean isComponent()\nclass ComponentEnabledSetting extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false)")
        @Deprecated
        private void __metadata() {}


        //@formatter:on
        // End of generated code

    }

    /**
     * Listener for changes in permissions granted to a UID.
     *
@@ -7675,6 +7889,9 @@ public abstract class PackageManager {
     * This setting will override any enabled state which may have been set by the component in its
     * manifest.
     *
     * <p>Consider using {@link #setComponentEnabledSettings(List)} if multiple components need to
     * be updated atomically.
     *
     * @param componentName The component to enable
     * @param newState The new enabled state for the component.
     * @param flags Optional behavior flags.
@@ -7684,6 +7901,32 @@ public abstract class PackageManager {
    public abstract void setComponentEnabledSetting(@NonNull ComponentName componentName,
            @EnabledState int newState, @EnabledFlags int flags);

    /**
     * Set the enabled settings for package components such as activities, receivers, services and
     * providers. This setting will override any enabled state which may have been set by the
     * component in its manifest.
     *
     * <p>This api accepts a list of component changes, and applies them all atomically. The
     * application can use this api if components have dependencies and need to be updated
     * atomically.
     *
     * <p>The permission is not required if target components are running under the same uid with
     * the caller.
     *
     * @param settings The list of component enabled settings to update. Note that an
     *                 {@link IllegalArgumentException} is thrown if the duplicated component name
     *                 is in the list or there's a conflict {@link #DONT_KILL_APP} flag between
     *                 different components in the same package.
     *
     * @see #setComponentEnabledSetting(ComponentName, int, int)
     */
    @RequiresPermission(value = android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE,
            conditional = true)
    public void setComponentEnabledSettings(@NonNull List<ComponentEnabledSetting> settings) {
        throw new UnsupportedOperationException("setComponentEnabledSettings not implemented"
                + "in subclass");
    }

    /**
     * Return the enabled setting for a package component (activity,
     * receiver, service, provider).  This returns the last value set by
Loading