Add API to skip application enable in install flow

This CL addes a new API to PackageInstaller.SessionParams that can be
used to skip the app enable step during the package install flow. This
can be used by installers to keep the app's existing enabled state
after a upgrade instead of setting it to enabled by default.

This also corrects the variable userId used in the enable step to
currentUserId that was preventing it from enabling the app when
installed for all users.

Bug: 244430570
Test: atest PackageManagerShellCommandTest#testAppUpdateSkipEnable
Change-Id: I42b003f8c42a7f8c45a581bd9383c78090462d0f
This commit is contained in:
William Loh
2022-10-08 01:13:50 +00:00
parent 90cef8f473
commit e677b4717e
9 changed files with 85 additions and 8 deletions

View File

@@ -11736,6 +11736,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;
@@ -11787,6 +11788,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();
@@ -11819,6 +11821,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);

View File

@@ -61,4 +61,6 @@ interface IPackageInstallerSession {
int getInstallFlags();
void requestUserPreapproval(in PackageInstaller.PreapprovalDetails details, in IntentSender statusReceiver);
boolean isKeepApplicationEnabledSetting();
}

View File

@@ -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<SessionParams>
@@ -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<SessionInfo>

View File

@@ -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<String> 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;
}

View File

@@ -2036,7 +2036,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,
@@ -2086,16 +2087,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);
}
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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(

View File

@@ -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);
}