diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 0dcfd38294b93..c789f877976fe 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -37,6 +37,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageManager.DeleteFlags; import android.content.pm.PackageManager.InstallReason; +import android.content.pm.PackageManager.InstallScenario; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; @@ -1500,6 +1501,14 @@ public class PackageInstaller { public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; /** {@hide} */ public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN; + /** + * {@hide} + * + * This flag indicates which installation scenario best describes this session. The system + * may use this value when making decisions about how to handle the installation, such as + * prioritizing system health or user experience. + */ + public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long sizeBytes = -1; @@ -1563,6 +1572,7 @@ public class PackageInstaller { installFlags = source.readInt(); installLocation = source.readInt(); installReason = source.readInt(); + installScenario = source.readInt(); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null); @@ -1594,6 +1604,7 @@ public class PackageInstaller { ret.installFlags = installFlags; ret.installLocation = installLocation; ret.installReason = installReason; + ret.installScenario = installScenario; ret.sizeBytes = sizeBytes; ret.appPackageName = appPackageName; ret.appIcon = appIcon; // not a copy. @@ -2019,6 +2030,8 @@ public class PackageInstaller { pw.printPair("mode", mode); pw.printHexPair("installFlags", installFlags); pw.printPair("installLocation", installLocation); + pw.printPair("installReason", installReason); + pw.printPair("installScenario", installScenario); pw.printPair("sizeBytes", sizeBytes); pw.printPair("appPackageName", appPackageName); pw.printPair("appIcon", (appIcon != null)); @@ -2052,6 +2065,7 @@ public class PackageInstaller { dest.writeInt(installFlags); dest.writeInt(installLocation); dest.writeInt(installReason); + dest.writeInt(installScenario); dest.writeLong(sizeBytes); dest.writeString(appPackageName); dest.writeParcelable(appIcon, flags); @@ -2170,6 +2184,8 @@ public class PackageInstaller { /** {@hide} */ public @InstallReason int installReason; /** {@hide} */ + public @InstallReason int installScenario; + /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public long sizeBytes; /** {@hide} */ @@ -2248,6 +2264,7 @@ public class PackageInstaller { mode = source.readInt(); installReason = source.readInt(); + installScenario = source.readInt(); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null); @@ -2795,6 +2812,7 @@ public class PackageInstaller { dest.writeInt(mode); dest.writeInt(installReason); + dest.writeInt(installScenario); dest.writeLong(sizeBytes); dest.writeString(appPackageName); dest.writeParcelable(appIcon, flags); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 044b3b2e8284a..6d742c7238866 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1317,6 +1317,60 @@ public abstract class PackageManager { */ public static final int INSTALL_REASON_ROLLBACK = 5; + /** @hide */ + @IntDef(prefix = { "INSTALL_SCENARIO_" }, value = { + INSTALL_SCENARIO_DEFAULT, + INSTALL_SCENARIO_FAST, + INSTALL_SCENARIO_BULK, + INSTALL_SCENARIO_BULK_SECONDARY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface InstallScenario {} + + /** + * A value to indicate the lack of CUJ information, disabling all installation scenario logic. + * + * @hide + */ + public static final int INSTALL_SCENARIO_DEFAULT = 0; + + /** + * Installation scenario providing the fastest “install button to launch" experience possible. + * + * @hide + */ + public static final int INSTALL_SCENARIO_FAST = 1; + + /** + * Installation scenario indicating a bulk operation with the desired result of a fully + * optimized application. If the system is busy or resources are scarce the system will + * perform less work to avoid impacting system health. + * + * Examples of bulk installation scenarios might include device restore, background updates of + * multiple applications, or user-triggered updates for all applications. + * + * The decision to use BULK or BULK_SECONDARY should be based on the desired user experience. + * BULK_SECONDARY operations may take less time to complete but, when they do, will produce + * less optimized applications. The device state (e.g. memory usage or battery status) should + * not be considered when making this decision as those factors are taken into account by the + * Package Manager when acting on the installation scenario. + * + * @hide + */ + public static final int INSTALL_SCENARIO_BULK = 2; + + /** + * Installation scenario indicating a bulk operation that prioritizes minimal system health + * impact over application optimization. The application may undergo additional optimization + * if the system is idle and system resources are abundant. The more elements of a bulk + * operation that are marked BULK_SECONDARY, the faster the entire bulk operation will be. + * + * See the comments for INSTALL_SCENARIO_BULK for more information. + * + * @hide + */ + public static final int INSTALL_SCENARIO_BULK_SECONDARY = 3; + /** @hide */ @IntDef(prefix = { "UNINSTALL_REASON_" }, value = { UNINSTALL_REASON_UNKNOWN, diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index c10d394d63442..2b8a5cb665be2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -37,16 +37,11 @@ import static android.system.OsConstants.O_RDONLY; import static android.system.OsConstants.O_WRONLY; import static com.android.internal.util.XmlUtils.readBitmapAttribute; -import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readByteArrayAttribute; -import static com.android.internal.util.XmlUtils.readIntAttribute; -import static com.android.internal.util.XmlUtils.readLongAttribute; import static com.android.internal.util.XmlUtils.readStringAttribute; import static com.android.internal.util.XmlUtils.readUriAttribute; import static com.android.internal.util.XmlUtils.writeBooleanAttribute; import static com.android.internal.util.XmlUtils.writeByteArrayAttribute; -import static com.android.internal.util.XmlUtils.writeIntAttribute; -import static com.android.internal.util.XmlUtils.writeLongAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; import static com.android.internal.util.XmlUtils.writeUriAttribute; import static com.android.server.pm.PackageInstallerService.prepareStageDir; @@ -156,7 +151,6 @@ import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.ByteArrayOutputStream; import java.io.File; @@ -759,6 +753,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.mode = params.mode; info.installReason = params.installReason; + info.installScenario = params.installScenario; info.sizeBytes = params.sizeBytes; info.appPackageName = mPackageName != null ? mPackageName : params.appPackageName; if (includeIcon) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e95b1a2b9d7a8..c70386e5cc3ec 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15198,6 +15198,7 @@ public class PackageManagerService extends IPackageManager.Stub final int autoRevokePermissionsMode; final PackageParser.SigningDetails signingDetails; final int installReason; + final int mInstallScenario; @Nullable MultiPackageInstallParams mParentInstallParams; final boolean forceQueryableOverride; final int mDataLoaderType; @@ -15220,6 +15221,7 @@ public class PackageManagerService extends IPackageManager.Stub this.autoRevokePermissionsMode = MODE_DEFAULT; this.signingDetails = PackageParser.SigningDetails.UNKNOWN; this.installReason = PackageManager.INSTALL_REASON_UNKNOWN; + this.mInstallScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; this.forceQueryableOverride = false; this.mDataLoaderType = DataLoaderType.NONE; this.requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; @@ -15233,6 +15235,7 @@ public class PackageManagerService extends IPackageManager.Stub move = null; installReason = fixUpInstallReason( installSource.installerPackageName, installerUid, sessionParams.installReason); + mInstallScenario = sessionParams.installScenario; this.observer = observer; installFlags = sessionParams.installFlags; this.installSource = installSource; @@ -15956,6 +15959,7 @@ public class PackageManagerService extends IPackageManager.Stub final int traceCookie; final PackageParser.SigningDetails signingDetails; final int installReason; + final int mInstallScenario; final boolean forceQueryableOverride; final int mDataLoaderType; @@ -15971,7 +15975,8 @@ public class PackageManagerService extends IPackageManager.Stub List whitelistedRestrictedPermissions, int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, - int installReason, boolean forceQueryableOverride, int dataLoaderType) { + int installReason, int installScenario, boolean forceQueryableOverride, + int dataLoaderType) { this.origin = origin; this.move = move; this.installFlags = installFlags; @@ -15988,6 +15993,7 @@ public class PackageManagerService extends IPackageManager.Stub this.traceCookie = traceCookie; this.signingDetails = signingDetails; this.installReason = installReason; + this.mInstallScenario = installScenario; this.forceQueryableOverride = forceQueryableOverride; this.mDataLoaderType = dataLoaderType; } @@ -16000,7 +16006,8 @@ public class PackageManagerService extends IPackageManager.Stub params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions, params.autoRevokePermissionsMode, params.traceMethod, params.traceCookie, params.signingDetails, - params.installReason, params.forceQueryableOverride, params.mDataLoaderType); + params.installReason, params.mInstallScenario, params.forceQueryableOverride, + params.mDataLoaderType); } abstract int copyApk(); @@ -16089,8 +16096,8 @@ public class PackageManagerService extends IPackageManager.Stub super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY, null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0, PackageParser.SigningDetails.UNKNOWN, - PackageManager.INSTALL_REASON_UNKNOWN, false, - DataLoaderType.NONE); + PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT, + false, DataLoaderType.NONE); this.codeFile = (codePath != null) ? new File(codePath) : null; }