diff --git a/core/api/current.txt b/core/api/current.txt index 5f4fb58b67051..7cfb7f46b57f6 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -11735,6 +11735,7 @@ package android.content.pm { method @NonNull public int[] getChildSessionIds(); method @NonNull public String[] getNames() throws java.io.IOException; method public int getParentSessionId(); + method public boolean isKeepApplicationEnabledSetting(); method public boolean isMultiPackage(); method public boolean isStaged(); method @NonNull public java.io.InputStream openRead(@NonNull String) throws java.io.IOException; @@ -11786,6 +11787,7 @@ package android.content.pm { method public boolean hasParentSessionId(); method public boolean isActive(); method public boolean isCommitted(); + method public boolean isKeepApplicationEnabledSetting(); method public boolean isMultiPackage(); method public boolean isSealed(); method public boolean isStaged(); @@ -11818,6 +11820,7 @@ package android.content.pm { method public void setInstallLocation(int); method public void setInstallReason(int); method public void setInstallScenario(int); + method public void setKeepApplicationEnabledSetting(); method public void setMultiPackage(); method public void setOriginatingUid(int); method public void setOriginatingUri(@Nullable android.net.Uri); diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl index 1fc6bdaa963a9..7d9c64add492d 100644 --- a/core/java/android/content/pm/IPackageInstallerSession.aidl +++ b/core/java/android/content/pm/IPackageInstallerSession.aidl @@ -61,4 +61,6 @@ interface IPackageInstallerSession { int getInstallFlags(); void requestUserPreapproval(in PackageInstaller.PreapprovalDetails details, in IntentSender statusReceiver); + + boolean isKeepApplicationEnabledSetting(); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index d7686e22756e2..35518276ac095 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1717,6 +1717,18 @@ public class PackageInstaller { e.rethrowFromSystemServer(); } } + + /** + * @return {@code true} if this session will keep the existing application enabled setting + * after installation. + */ + public boolean isKeepApplicationEnabledSetting() { + try { + return mSession.isKeepApplicationEnabledSetting(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } /** @@ -1855,6 +1867,8 @@ public class PackageInstaller { public boolean forceQueryableOverride; /** {@hide} */ public int requireUserAction = USER_ACTION_UNSPECIFIED; + /** {@hide} */ + public boolean keepApplicationEnabledSetting = false; /** * Construct parameters for a new package install session. @@ -1899,6 +1913,7 @@ public class PackageInstaller { rollbackDataPolicy = source.readInt(); requireUserAction = source.readInt(); packageSource = source.readInt(); + keepApplicationEnabledSetting = source.readBoolean(); } /** {@hide} */ @@ -1929,6 +1944,7 @@ public class PackageInstaller { ret.rollbackDataPolicy = rollbackDataPolicy; ret.requireUserAction = requireUserAction; ret.packageSource = packageSource; + ret.keepApplicationEnabledSetting = keepApplicationEnabledSetting; return ret; } @@ -2415,6 +2431,14 @@ public class PackageInstaller { this.installScenario = installScenario; } + /** + * Request to keep the original application enabled setting. This will prevent the + * application from being enabled if it was previously in a disabled state. + */ + public void setKeepApplicationEnabledSetting() { + this.keepApplicationEnabledSetting = true; + } + /** {@hide} */ public void dump(IndentingPrintWriter pw) { pw.printPair("mode", mode); @@ -2443,6 +2467,7 @@ public class PackageInstaller { pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode); pw.printPair("dataLoaderParams", dataLoaderParams); pw.printPair("rollbackDataPolicy", rollbackDataPolicy); + pw.printPair("keepApplicationEnabledSetting", keepApplicationEnabledSetting); pw.println(); } @@ -2483,6 +2508,7 @@ public class PackageInstaller { dest.writeInt(rollbackDataPolicy); dest.writeInt(requireUserAction); dest.writeInt(packageSource); + dest.writeBoolean(keepApplicationEnabledSetting); } public static final Parcelable.Creator @@ -2684,6 +2710,9 @@ public class PackageInstaller { /** @hide */ public boolean isPreapprovalRequested; + /** @hide */ + public boolean keepApplicationEnabledSetting; + /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public SessionInfo() { @@ -2737,6 +2766,7 @@ public class PackageInstaller { requireUserAction = source.readInt(); installerUid = source.readInt(); packageSource = source.readInt(); + keepApplicationEnabledSetting = source.readBoolean(); } /** @@ -3268,6 +3298,14 @@ public class PackageInstaller { return installerUid; } + /** + * Returns {@code true} if this session will keep the existing application enabled setting + * after installation. + */ + public boolean isKeepApplicationEnabledSetting() { + return keepApplicationEnabledSetting; + } + @Override public int describeContents() { return 0; @@ -3317,6 +3355,7 @@ public class PackageInstaller { dest.writeInt(requireUserAction); dest.writeInt(installerUid); dest.writeInt(packageSource); + dest.writeBoolean(keepApplicationEnabledSetting); } public static final Parcelable.Creator diff --git a/services/core/java/com/android/server/pm/InstallArgs.java b/services/core/java/com/android/server/pm/InstallArgs.java index a94a4e2a70be7..ced547c358990 100644 --- a/services/core/java/com/android/server/pm/InstallArgs.java +++ b/services/core/java/com/android/server/pm/InstallArgs.java @@ -59,6 +59,7 @@ final class InstallArgs { final boolean mForceQueryableOverride; final int mDataLoaderType; final int mPackageSource; + final boolean mKeepApplicationEnabledSetting; // The list of instruction sets supported by this app. This is currently // only used during the rmdex() phase to clean up resources. We can get rid of this @@ -72,7 +73,8 @@ final class InstallArgs { List allowlistedRestrictedPermissions, int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, int installReason, int installScenario, - boolean forceQueryableOverride, int dataLoaderType, int packageSource) { + boolean forceQueryableOverride, int dataLoaderType, int packageSource, + boolean keepApplicationEnabledSetting) { mOriginInfo = originInfo; mMoveInfo = moveInfo; mInstallFlags = installFlags; @@ -93,6 +95,7 @@ final class InstallArgs { mForceQueryableOverride = forceQueryableOverride; mDataLoaderType = dataLoaderType; mPackageSource = packageSource; + mKeepApplicationEnabledSetting = keepApplicationEnabledSetting; } /** @@ -104,7 +107,7 @@ final class InstallArgs { null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0, SigningDetails.UNKNOWN, PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT, false, DataLoaderType.NONE, - PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED); + PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, false); mCodeFile = (codePath != null) ? new File(codePath) : null; } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 1de5621bb5f41..78e419078bde4 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -2044,7 +2044,8 @@ final class InstallPackageHelper { Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName); } // Enable system package for requested users - if (installedForUsers != null) { + if (installedForUsers != null + && !installRequest.isKeepApplicationEnabledSetting()) { for (int origUserId : installedForUsers) { if (userId == UserHandle.USER_ALL || userId == origUserId) { ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, @@ -2094,16 +2095,22 @@ final class InstallPackageHelper { if (userId != UserHandle.USER_ALL) { // It's implied that when a user requests installation, they want the app to - // be installed and enabled. + // be installed and enabled. The caller, however, can explicitly specify to + // keep the existing enabled state. ps.setInstalled(true, userId); - ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName); + if (!installRequest.isKeepApplicationEnabledSetting()) { + ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, + installerPackageName); + } } else if (allUsers != null) { // The caller explicitly specified INSTALL_ALL_USERS flag. // Thus, updating the settings to install the app for all users. for (int currentUserId : allUsers) { ps.setInstalled(true, currentUserId); - ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, - installerPackageName); + if (!installRequest.isKeepApplicationEnabledSetting()) { + ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId, + installerPackageName); + } } } diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java index 71571dc4f3066..5974a9cbab676 100644 --- a/services/core/java/com/android/server/pm/InstallRequest.java +++ b/services/core/java/com/android/server/pm/InstallRequest.java @@ -128,7 +128,8 @@ final class InstallRequest { params.mAutoRevokePermissionsMode, params.mTraceMethod, params.mTraceCookie, params.mSigningDetails, params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride, - params.mDataLoaderType, params.mPackageSource); + params.mDataLoaderType, params.mPackageSource, + params.mKeepApplicationEnabledSetting); mPackageMetrics = new PackageMetrics(this); mIsInstallInherit = params.mIsInherit; mSessionId = params.mSessionId; @@ -498,6 +499,10 @@ final class InstallRequest { return mScanResult.mChangedAbiCodePath; } + public boolean isKeepApplicationEnabledSetting() { + return mInstallArgs == null ? false : mInstallArgs.mKeepApplicationEnabledSetting; + } + public boolean isForceQueryableOverride() { return mInstallArgs != null && mInstallArgs.mForceQueryableOverride; } diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java index 69ced1b39585d..2b6398af348e7 100644 --- a/services/core/java/com/android/server/pm/InstallingSession.java +++ b/services/core/java/com/android/server/pm/InstallingSession.java @@ -98,6 +98,7 @@ class InstallingSession { final boolean mIsInherit; final int mSessionId; final int mRequireUserAction; + final boolean mKeepApplicationEnabledSetting; // For move install InstallingSession(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer, @@ -130,6 +131,7 @@ class InstallingSession { mIsInherit = false; mSessionId = -1; mRequireUserAction = USER_ACTION_UNSPECIFIED; + mKeepApplicationEnabledSetting = false; } InstallingSession(int sessionId, File stagedDir, IPackageInstallObserver2 observer, @@ -163,6 +165,7 @@ class InstallingSession { mIsInherit = sessionParams.mode == MODE_INHERIT_EXISTING; mSessionId = sessionId; mRequireUserAction = sessionParams.requireUserAction; + mKeepApplicationEnabledSetting = sessionParams.keepApplicationEnabledSetting; } @Override diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 2ee12bf978234..3983acfe9d2df 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -269,6 +269,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String ATTR_SIGNATURE = "signature"; private static final String ATTR_CHECKSUM_KIND = "checksumKind"; private static final String ATTR_CHECKSUM_VALUE = "checksumValue"; + private static final String ATTR_KEEP_APPLICATION_ENABLED_SETTING = + "keepApplicationEnabledSetting"; private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill"; private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT; @@ -1098,6 +1100,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.requireUserAction = params.requireUserAction; info.installerUid = mInstallerUid; info.packageSource = params.packageSource; + info.keepApplicationEnabledSetting = params.keepApplicationEnabledSetting; } return info; } @@ -4310,6 +4313,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mPreapprovalRequested.set(true); } + @Override + public boolean isKeepApplicationEnabledSetting() { + return params.keepApplicationEnabledSetting; + } + void setSessionReady() { synchronized (mLock) { // Do not allow destroyed/failed session to change state @@ -4691,6 +4699,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride); writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid); out.attributeInt(null, ATTR_INSTALL_REASON, params.installReason); + writeBooleanAttribute(out, ATTR_KEEP_APPLICATION_ENABLED_SETTING, + params.keepApplicationEnabledSetting); final boolean isDataLoader = params.dataLoaderParams != null; writeBooleanAttribute(out, ATTR_IS_DATALOADER, isDataLoader); @@ -4852,6 +4862,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID); params.installReason = in.getAttributeInt(null, ATTR_INSTALL_REASON); params.packageSource = in.getAttributeInt(null, ATTR_PACKAGE_SOURCE); + params.keepApplicationEnabledSetting = in.getAttributeBoolean(null, + ATTR_KEEP_APPLICATION_ENABLED_SETTING, false); if (in.getAttributeBoolean(null, ATTR_IS_DATALOADER, false)) { params.dataLoaderParams = new DataLoaderParams( diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index cc1306dbc2b36..e1efc612224c4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -3234,6 +3234,9 @@ class PackageManagerShellCommand extends ShellCommand { case "--skip-verification": sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION; break; + case "--skip-enable": + sessionParams.setKeepApplicationEnabledSetting(); + break; default: throw new IllegalArgumentException("Unknown option " + opt); }