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

Commit 28b62162 authored by Chun-Wei Wang's avatar Chun-Wei Wang Committed by Android (Google) Code Review
Browse files

Merge "Install constraints API"

parents b996c643 1c61ab5c
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -11663,6 +11663,7 @@ package android.content.pm {
  public class PackageInstaller {
    method public void abandonSession(int);
    method public void checkInstallConstraints(@NonNull java.util.List<java.lang.String>, @NonNull android.content.pm.PackageInstaller.InstallConstraints, @NonNull java.util.function.Consumer<android.content.pm.PackageInstaller.InstallConstraintsResult>);
    method public int createSession(@NonNull android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
    method @Deprecated @Nullable public android.content.pm.PackageInstaller.SessionInfo getActiveStagedSession();
    method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getActiveStagedSessions();
@@ -11707,6 +11708,35 @@ package android.content.pm {
    field public static final int STATUS_SUCCESS = 0; // 0x0
  }
  public static final class PackageInstaller.InstallConstraints implements android.os.Parcelable {
    method public int describeContents();
    method public boolean isRequireAppNotForeground();
    method public boolean isRequireAppNotInteracting();
    method public boolean isRequireAppNotTopVisible();
    method public boolean isRequireDeviceIdle();
    method public boolean isRequireNotInCall();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.InstallConstraints> CREATOR;
    field @NonNull public static final android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE;
  }
  public static final class PackageInstaller.InstallConstraints.Builder {
    ctor public PackageInstaller.InstallConstraints.Builder();
    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints build();
    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotForeground();
    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotInteracting();
    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotTopVisible();
    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireDeviceIdle();
    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireNotInCall();
  }
  public static final class PackageInstaller.InstallConstraintsResult implements android.os.Parcelable {
    method public int describeContents();
    method public boolean isAllConstraintsSatisfied();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.InstallConstraintsResult> CREATOR;
  }
  public static final class PackageInstaller.PreapprovalDetails implements android.os.Parcelable {
    method public int describeContents();
    method @Nullable public android.graphics.Bitmap getIcon();
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.pm.PackageInstaller;
import android.content.pm.ParceledListSlice;
import android.content.pm.VersionedPackage;
import android.content.IntentSender;
import android.os.RemoteCallback;

import android.graphics.Bitmap;

@@ -66,4 +67,6 @@ interface IPackageInstaller {

    void setAllowUnlimitedSilentUpdates(String installerPackageName);
    void setSilentUpdatesThrottleTime(long throttleTimeInSeconds);
    void checkInstallConstraints(String installerPackageName, in List<String> packageNames,
            in PackageInstaller.InstallConstraints constraints, in RemoteCallback callback);
}
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.content.pm;

parcelable PackageInstaller.InstallConstraints;
parcelable PackageInstaller.SessionParams;
parcelable PackageInstaller.SessionInfo;
parcelable PackageInstaller.PreapprovalDetails;
+384 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityManager;
@@ -57,6 +58,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.ParcelableException;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -89,6 +91,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * Offers the ability to install, upgrade, and remove applications on the
@@ -853,6 +856,29 @@ public class PackageInstaller {
        }
    }

    /**
     * Check if install constraints are satisfied for the given packages.
     *
     * Note this query result is just a hint and subject to race because system states could
     * change anytime in-between this query and committing the session.
     *
     * The result is returned by a callback because some constraints might take a long time
     * to evaluate.
     */
    public void checkInstallConstraints(@NonNull List<String> packageNames,
            @NonNull InstallConstraints constraints,
            @NonNull Consumer<InstallConstraintsResult> callback) {
        try {
            var remoteCallback = new RemoteCallback(b -> {
                callback.accept(b.getParcelable("result", InstallConstraintsResult.class));
            });
            mInstaller.checkInstallConstraints(
                    mInstallerPackageName, packageNames, constraints, remoteCallback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Events for observing session lifecycle.
     * <p>
@@ -3647,4 +3673,362 @@ public class PackageInstaller {
        // End of generated code

    }

    /**
     * The callback result of {@link #checkInstallConstraints(List, InstallConstraints, Consumer)}.
     */
    @DataClass(genParcelable = true, genHiddenConstructor = true)
    public static final class InstallConstraintsResult implements Parcelable {
        /**
         * True if all constraints are satisfied.
         */
        private boolean mAllConstraintsSatisfied;



        // 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/PackageInstaller.java
        //
        // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
        //   Settings > Editor > Code Style > Formatter Control
        //@formatter:off


        /**
         * Creates a new InstallConstraintsResult.
         *
         * @param allConstraintsSatisfied
         *   True if all constraints are satisfied.
         * @hide
         */
        @DataClass.Generated.Member
        public InstallConstraintsResult(
                boolean allConstraintsSatisfied) {
            this.mAllConstraintsSatisfied = allConstraintsSatisfied;

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

        /**
         * True if all constraints are satisfied.
         */
        @DataClass.Generated.Member
        public boolean isAllConstraintsSatisfied() {
            return mAllConstraintsSatisfied;
        }

        @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 (mAllConstraintsSatisfied) flg |= 0x1;
            dest.writeByte(flg);
        }

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

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

            byte flg = in.readByte();
            boolean allConstraintsSatisfied = (flg & 0x1) != 0;

            this.mAllConstraintsSatisfied = allConstraintsSatisfied;

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

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

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

        @DataClass.Generated(
                time = 1668650523745L,
                codegenVersion = "1.0.23",
                sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
                inputSignatures = "private  boolean mAllConstraintsSatisfied\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
        @Deprecated
        private void __metadata() {}


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

    }

    /**
     * A class to encapsulate constraints for installation.
     *
     * When used with {@link #checkInstallConstraints(List, InstallConstraints, Consumer)}, it
     * specifies the conditions to check against for the packages in question. This can be used
     * by app stores to deliver auto updates without disrupting the user experience (referred as
     * gentle update) - for example, an app store might hold off updates when it find out the
     * app to update is interacting with the user.
     *
     * Use {@link Builder} to create a new instance and call mutator methods to add constraints.
     * If no mutators were called, default constraints will be generated which implies no
     * constraints. It is recommended to use preset constraints which are useful in most
     * cases.
     *
     * For the purpose of gentle update, it is recommended to always use {@link #GENTLE_UPDATE}
     * for the system knows best how to do it. It will also benefits the installer as the
     * platform evolves and add more constraints to improve the accuracy and efficiency of
     * gentle update.
     *
     * Note the constraints are applied transitively. If app Foo is used by app Bar (via shared
     * library or bounded service), the constraints will also be applied to Bar.
     */
    @DataClass(genParcelable = true, genHiddenConstructor = true)
    public static final class InstallConstraints implements Parcelable {
        /**
         * Preset constraints suitable for gentle update.
         */
        @NonNull
        public static final InstallConstraints GENTLE_UPDATE =
                new Builder().requireAppNotInteracting().build();

        private final boolean mRequireDeviceIdle;
        private final boolean mRequireAppNotForeground;
        private final boolean mRequireAppNotInteracting;
        private final boolean mRequireAppNotTopVisible;
        private final boolean mRequireNotInCall;

        /**
         * Builder class for constructing {@link InstallConstraints}.
         */
        public static final class Builder {
            private boolean mRequireDeviceIdle;
            private boolean mRequireAppNotForeground;
            private boolean mRequireAppNotInteracting;
            private boolean mRequireAppNotTopVisible;
            private boolean mRequireNotInCall;

            /**
             * This constraint requires the device is idle.
             */
            @SuppressLint("BuilderSetStyle")
            @NonNull
            public Builder requireDeviceIdle() {
                mRequireDeviceIdle = true;
                return this;
            }

            /**
             * This constraint requires the app in question is not in the foreground.
             */
            @SuppressLint("BuilderSetStyle")
            @NonNull
            public Builder requireAppNotForeground() {
                mRequireAppNotForeground = true;
                return this;
            }

            /**
             * This constraint requires the app in question is not interacting with the user.
             * User interaction includes:
             * <ul>
             *     <li>playing or recording audio/video</li>
             *     <li>sending or receiving network data</li>
             *     <li>being visible to the user</li>
             * </ul>
             */
            @SuppressLint("BuilderSetStyle")
            @NonNull
            public Builder requireAppNotInteracting() {
                mRequireAppNotInteracting = true;
                return this;
            }

            /**
             * This constraint requires the app in question is not top-visible to the user.
             * A top-visible app is showing UI at the top of the screen that the user is
             * interacting with.
             *
             * Note this constraint is a subset of {@link #requireAppNotForeground()}
             * because a top-visible app is also a foreground app. This is also a subset
             * of {@link #requireAppNotInteracting()} because a top-visible app is interacting
             * with the user.
             */
            @SuppressLint("BuilderSetStyle")
            @NonNull
            public Builder requireAppNotTopVisible() {
                mRequireAppNotTopVisible = true;
                return this;
            }

            /**
             * This constraint requires there is no ongoing call in the device.
             */
            @SuppressLint("BuilderSetStyle")
            @NonNull
            public Builder requireNotInCall() {
                mRequireNotInCall = true;
                return this;
            }

            /**
             * Builds a new {@link InstallConstraints} instance.
             */
            @NonNull
            public InstallConstraints build() {
                return new InstallConstraints(mRequireDeviceIdle, mRequireAppNotForeground,
                        mRequireAppNotInteracting, mRequireAppNotTopVisible, mRequireNotInCall);
            }
        }



        // 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/PackageInstaller.java
        //
        // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
        //   Settings > Editor > Code Style > Formatter Control
        //@formatter:off


        /**
         * Creates a new InstallConstraints.
         *
         * @hide
         */
        @DataClass.Generated.Member
        public InstallConstraints(
                boolean requireDeviceIdle,
                boolean requireAppNotForeground,
                boolean requireAppNotInteracting,
                boolean requireAppNotTopVisible,
                boolean requireNotInCall) {
            this.mRequireDeviceIdle = requireDeviceIdle;
            this.mRequireAppNotForeground = requireAppNotForeground;
            this.mRequireAppNotInteracting = requireAppNotInteracting;
            this.mRequireAppNotTopVisible = requireAppNotTopVisible;
            this.mRequireNotInCall = requireNotInCall;

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

        @DataClass.Generated.Member
        public boolean isRequireDeviceIdle() {
            return mRequireDeviceIdle;
        }

        @DataClass.Generated.Member
        public boolean isRequireAppNotForeground() {
            return mRequireAppNotForeground;
        }

        @DataClass.Generated.Member
        public boolean isRequireAppNotInteracting() {
            return mRequireAppNotInteracting;
        }

        @DataClass.Generated.Member
        public boolean isRequireAppNotTopVisible() {
            return mRequireAppNotTopVisible;
        }

        @DataClass.Generated.Member
        public boolean isRequireNotInCall() {
            return mRequireNotInCall;
        }

        @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 (mRequireDeviceIdle) flg |= 0x1;
            if (mRequireAppNotForeground) flg |= 0x2;
            if (mRequireAppNotInteracting) flg |= 0x4;
            if (mRequireAppNotTopVisible) flg |= 0x8;
            if (mRequireNotInCall) flg |= 0x10;
            dest.writeByte(flg);
        }

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

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

            byte flg = in.readByte();
            boolean requireDeviceIdle = (flg & 0x1) != 0;
            boolean requireAppNotForeground = (flg & 0x2) != 0;
            boolean requireAppNotInteracting = (flg & 0x4) != 0;
            boolean requireAppNotTopVisible = (flg & 0x8) != 0;
            boolean requireNotInCall = (flg & 0x10) != 0;

            this.mRequireDeviceIdle = requireDeviceIdle;
            this.mRequireAppNotForeground = requireAppNotForeground;
            this.mRequireAppNotInteracting = requireAppNotInteracting;
            this.mRequireAppNotTopVisible = requireAppNotTopVisible;
            this.mRequireNotInCall = requireNotInCall;

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

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

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

        @DataClass.Generated(
                time = 1668650523752L,
                codegenVersion = "1.0.23",
                sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
                inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final  boolean mRequireDeviceIdle\nprivate final  boolean mRequireAppNotForeground\nprivate final  boolean mRequireAppNotInteracting\nprivate final  boolean mRequireAppNotTopVisible\nprivate final  boolean mRequireNotInCall\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mRequireDeviceIdle\nprivate  boolean mRequireAppNotForeground\nprivate  boolean mRequireAppNotInteracting\nprivate  boolean mRequireAppNotTopVisible\nprivate  boolean mRequireNotInCall\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireDeviceIdle()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotForeground()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotInteracting()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotTopVisible()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireNotInCall()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
        @Deprecated
        private void __metadata() {}


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

    }

}
+4 −0
Original line number Diff line number Diff line
@@ -7291,6 +7291,10 @@
                 android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>

        <service android:name="com.android.server.pm.GentleUpdateHelper$Service"
            android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>

        <service
                android:name="com.android.server.autofill.AutofillCompatAccessibilityService"
                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
Loading