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

Commit 9458370e authored by Patrick Baumann's avatar Patrick Baumann
Browse files

Exposes way to bypass user action on update

Bug: 182487678
Test: atest CtsSilentUpdateHostTestCases
Change-Id: Idb56472544da378c95346329ddc2664400db37a6
Merged-In: Idb56472544da378c95346329ddc2664400db37a6
parent 346a71da
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ package android {
    field public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
    field public static final String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
    field public static final String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
    field public static final String UPDATE_PACKAGES_WITHOUT_USER_ACTION = "android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION";
    field public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
    field @Deprecated public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
    field public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT";
@@ -12348,6 +12349,7 @@ package android.content.pm {
    method public int getParentSessionId();
    method public float getProgress();
    method @Nullable public android.net.Uri getReferrerUri();
    method public int getRequireUserAction();
    method public int getSessionId();
    method public long getSize();
    method public int getStagedSessionErrorCode();
@@ -12372,6 +12374,9 @@ package android.content.pm {
    field public static final int STAGED_SESSION_NO_ERROR = 0; // 0x0
    field public static final int STAGED_SESSION_UNKNOWN = 3; // 0x3
    field public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; // 0x1
    field public static final int USER_ACTION_NOT_REQUIRED = 2; // 0x2
    field public static final int USER_ACTION_REQUIRED = 1; // 0x1
    field public static final int USER_ACTION_UNSPECIFIED = 0; // 0x0
  }
  public static class PackageInstaller.SessionParams implements android.os.Parcelable {
@@ -12389,6 +12394,7 @@ package android.content.pm {
    method public void setOriginatingUid(int);
    method public void setOriginatingUri(@Nullable android.net.Uri);
    method public void setReferrerUri(@Nullable android.net.Uri);
    method public void setRequireUserAction(boolean);
    method public void setSize(long);
    method public void setWhitelistedRestrictedPermissions(@Nullable java.util.Set<java.lang.String>);
    method public void writeToParcel(android.os.Parcel, int);
+105 −0
Original line number Diff line number Diff line
@@ -1565,6 +1565,8 @@ public class PackageInstaller {
        public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
        /** {@hide} */
        public boolean forceQueryableOverride;
        /** {@hide} */
        public Boolean requireUserAction;

        /**
         * Construct parameters for a new package install session.
@@ -1607,6 +1609,12 @@ public class PackageInstaller {
                dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
            }
            rollbackDataPolicy = source.readInt();
            int requireUserActionInt = source.readInt();
            requireUserAction = requireUserActionInt == 0
                    ? Boolean.FALSE
                    : requireUserActionInt == 1
                            ? Boolean.TRUE : null;

        }

        /** {@hide} */
@@ -1635,6 +1643,7 @@ public class PackageInstaller {
            ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
            ret.dataLoaderParams = dataLoaderParams;
            ret.rollbackDataPolicy = rollbackDataPolicy;
            ret.requireUserAction = requireUserAction;
            return ret;
        }

@@ -2028,6 +2037,41 @@ public class PackageInstaller {
            this.forceQueryableOverride = true;
        }

        /**
         * Optionally indicate whether user action should be required when the session is
         * committed.
         * <p>
         * Defaults to {@code true} for installers using the
         * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES android.permission
         * #REQUEST_INSTALL_PACKAGES} permission, and {@code false} otherwise. When {@code true},
         * installers will receive a {@link #STATUS_PENDING_USER_ACTION} callback once the
         * session is committed, indicating that the user is required for the install to proceed.
         * <p>
         * For installers using the {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES
         * android.permission.REQUEST_INSTALL_PACKAGES} permission, user action will not be
         * required when the following conditions are met:
         *
         * <ul>
         *     <li>{@code requireUserAction} is set to {@code false}.</li>
         *     <li>The being installed targets {@link android.os.Build.VERSION_CODES#Q API 29} or
         *     higher.</li>
         *     <li>The installer is the {@link InstallSourceInfo#getInstallingPackageName()
         *     installer of record} of an existing version of the app (i.e.: this install session
         *     is an app update or the installer is updating itself).</li>
         *     <li>The installer declares the
         *     {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION android
         *     .permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li>
         * </ul>
         * <p>
         * Note: The target API level requirement will advance in future Android versions.
         * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}
         *
         * @param requireUserAction whether user action should be required.
         */
        public void setRequireUserAction(boolean requireUserAction) {
            this.requireUserAction = requireUserAction;
        }

        /**
         * Sets the install scenario for this session, which describes the expected user journey.
         */
@@ -2058,6 +2102,7 @@ public class PackageInstaller {
            pw.printPair("isMultiPackage", isMultiPackage);
            pw.printPair("isStaged", isStaged);
            pw.printPair("forceQueryable", forceQueryableOverride);
            pw.printPair("requireUserAction", requireUserAction);
            pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
            pw.printPair("dataLoaderParams", dataLoaderParams);
            pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
@@ -2099,6 +2144,10 @@ public class PackageInstaller {
                dest.writeParcelable(null, flags);
            }
            dest.writeInt(rollbackDataPolicy);
            dest.writeInt(requireUserAction == Boolean.TRUE
                    ? 1
                    : requireUserAction == Boolean.FALSE
                            ? 0 : 2);
        }

        public static final Parcelable.Creator<SessionParams>
@@ -2165,6 +2214,31 @@ public class PackageInstaller {
         */
        public static final int STAGED_SESSION_CONFLICT = 4;

        /** @hide */
        @IntDef(prefix = {"USER_ACTION"}, value = {
                USER_ACTION_UNSPECIFIED,
                USER_ACTION_REQUIRED,
                USER_ACTION_NOT_REQUIRED
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface UserActionRequirement {}

        /**
         * The installer did not calling {@link SessionParams#setRequireUserAction(boolean)} to
         * specify whether user action should be required for the install.
         */
        public static final int USER_ACTION_UNSPECIFIED = 0;
        /**
         * The installer called {@link SessionParams#setRequireUserAction(boolean)} with
         * {@code true} to require user action for the install to complete.
         */
        public static final int USER_ACTION_REQUIRED = 1;
        /**
         * The installer called {@link SessionParams#setRequireUserAction(boolean)} with
         * {@code false} to request that user action not be required for this install.
         */
        public static final int USER_ACTION_NOT_REQUIRED = 2;

        /** {@hide} */
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
        public int sessionId;
@@ -2256,6 +2330,9 @@ public class PackageInstaller {
        /** {@hide} */
        public int rollbackDataPolicy;

        /** {@hide} */
        public Boolean requireUserAction;

        /** {@hide} */
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public SessionInfo() {
@@ -2305,6 +2382,11 @@ public class PackageInstaller {
            isCommitted = source.readBoolean();
            rollbackDataPolicy = source.readInt();
            createdMillis = source.readLong();
            int requireUserActionInt = source.readInt();
            requireUserAction = requireUserActionInt == 0
                    ? Boolean.FALSE
                    : requireUserActionInt == 1
                            ? Boolean.TRUE : null;
        }

        /**
@@ -2804,6 +2886,25 @@ public class PackageInstaller {
            return updatedMillis;
        }

        /**
         * Whether user action was required by the installer.
         *
         * <p>
         * Note: a return value of {@code USER_ACTION_NOT_REQUIRED} does not guarantee that the
         * install will not result in user action.
         *
         * @return {@link #USER_ACTION_NOT_REQUIRED}, {@link #USER_ACTION_REQUIRED} or
         *         {@link #USER_ACTION_UNSPECIFIED}
         */
        @UserActionRequirement
        public int getRequireUserAction() {
            return requireUserAction == null
                    ? USER_ACTION_UNSPECIFIED
                    : requireUserAction == Boolean.TRUE
                            ? USER_ACTION_REQUIRED
                            : USER_ACTION_NOT_REQUIRED;
        }

        @Override
        public int describeContents() {
            return 0;
@@ -2849,6 +2950,10 @@ public class PackageInstaller {
            dest.writeBoolean(isCommitted);
            dest.writeInt(rollbackDataPolicy);
            dest.writeLong(createdMillis);
            dest.writeInt(requireUserAction == Boolean.TRUE
                    ? 1
                    : requireUserAction == Boolean.FALSE
                            ? 0 : 2);
        }

        public static final Parcelable.Creator<SessionInfo>
+3 −2
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ public class ApkLiteParseUtils {
            final String packagePath = packageFile.getAbsolutePath();
            return input.success(
                    new PackageLite(packagePath, baseApk.getPath(), baseApk, null,
                            null, null, null, null, null));
                            null, null, null, null, null, baseApk.getTargetSdkVersion()));
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
@@ -242,7 +242,8 @@ public class ApkLiteParseUtils {
                splitNameToFileName(baseApk)).getAbsolutePath() : baseApk.getPath();
        return input.success(
                new PackageLite(codePath, baseCodePath, baseApk, splitNames, isFeatureSplits,
                        usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes));
                        usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes,
                        baseApk.getTargetSdkVersion()));
    }

    /**
+11 −3
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ public class PackageLite {
    /** Major and minor version number of this package */
    private final int mVersionCodeMajor;
    private final int mVersionCode;
    private final int mTargetSdk;
    /** Revision code of base APK */
    private final int mBaseRevisionCode;
    /** Revision codes of any split APKs, ordered by parsed splitName */
@@ -99,7 +100,8 @@ public class PackageLite {

    public PackageLite(String path, String baseApkPath, ApkLite baseApk,
            String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames,
            String[] configForSplit, String[] splitApkPaths, int[] splitRevisionCodes) {
            String[] configForSplit, String[] splitApkPaths, int[] splitRevisionCodes,
            int targetSdk) {
        // The following paths may be different from the path in ApkLite because we
        // move or rename the APK files. Use parameters to indicate the correct paths.
        mPath = path;
@@ -125,6 +127,7 @@ public class PackageLite {
        mConfigForSplit = configForSplit;
        mSplitApkPaths = splitApkPaths;
        mSplitRevisionCodes = splitRevisionCodes;
        mTargetSdk = targetSdk;
    }

    /**
@@ -230,6 +233,11 @@ public class PackageLite {
        return mVersionCode;
    }

    @DataClass.Generated.Member
    public int getTargetSdk() {
        return mTargetSdk;
    }

    /**
     * Revision code of base APK
     */
@@ -349,10 +357,10 @@ public class PackageLite {
    }

    @DataClass.Generated(
            time = 1610596639255L,
            time = 1615914120261L,
            codegenVersion = "1.0.22",
            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java",
            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final  int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mProfileableByShell\nprivate final  boolean mUseEmbeddedDex\npublic  java.util.List<java.lang.String> getAllApkPaths()\npublic  long getLongVersionCode()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mTargetSdk\nprivate final  int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final  int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mProfileableByShell\nprivate final  boolean mUseEmbeddedDex\npublic  java.util.List<java.lang.String> getAllApkPaths()\npublic  long getLongVersionCode()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
    @Deprecated
    private void __metadata() {}

+13 −0
Original line number Diff line number Diff line
@@ -5653,6 +5653,19 @@
    <permission android:name="android.permission.SET_CLIP_SOURCE"
                android:protectionLevel="signature|recents" />

    <!-- Allows an application to request installs that update existing packages do so without
         user action via
         {@link android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(boolean)}.
         This permission only grants the ability to make the request and is not a guarantee that the
         request will be honored. In order to execute the install, the caller must also have the
         "android.permission.REQUEST_INSTALL_PACKAGES" or "android.permission.INSTALL_PACKAGES"
         permissions.
         <p>Protection level: normal
    -->
    <permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"
                android:protectionLevel="normal" />
    <uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"/>

    <!-- Attribution for Geofencing service. -->
    <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
    <!-- Attribution for Country Detector. -->
Loading