Merge "Add option to toggle all changes" into rvc-dev am: e57cfbae26

Change-Id: Ifcff8bb8bbaddaaf8776aec974b97b6867c9b5b6
This commit is contained in:
Automerger Merge Worker
2020-03-11 20:14:45 +00:00
5 changed files with 212 additions and 29 deletions

View File

@@ -163,6 +163,30 @@ interface IPlatformCompat
*/ */
boolean clearOverride(long changeId, String packageName); boolean clearOverride(long changeId, String packageName);
/**
* Enable all compatibility changes which have enabledAfterTargetSdk ==
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
* changes to take effect.
*
* @param packageName The package name of the app whose compatibility changes will be enabled.
* @param targetSdkVersion The targetSdkVersion for filtering the changes to be enabled.
*
* @return The number of changes that were enabled.
*/
int enableTargetSdkChanges(in String packageName, int targetSdkVersion);
/**
* Disable all compatibility changes which have enabledAfterTargetSdk ==
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
* changes to take effect.
*
* @param packageName The package name of the app whose compatibility changes will be disabled.
* @param targetSdkVersion The targetSdkVersion for filtering the changes to be disabled.
*
* @return The number of changes that were disabled.
*/
int disableTargetSdkChanges(in String packageName, int targetSdkVersion);
/** /**
* Revert overrides to compatibility changes. Kills the app to allow the changes to take effect. * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
* *

View File

@@ -2931,13 +2931,22 @@ final class ActivityManagerShellCommand extends ShellCommand {
final PlatformCompat platformCompat = (PlatformCompat) final PlatformCompat platformCompat = (PlatformCompat)
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
String toggleValue = getNextArgRequired(); String toggleValue = getNextArgRequired();
if (toggleValue.equals("reset-all")) { boolean toggleAll = false;
final String packageName = getNextArgRequired(); int targetSdkVersion = -1;
pw.println("Reset all changes for " + packageName + " to default value."); long changeId = -1;
platformCompat.clearOverrides(packageName);
return 0; if (toggleValue.endsWith("-all")) {
toggleValue = toggleValue.substring(0, toggleValue.lastIndexOf("-all"));
toggleAll = true;
if (!toggleValue.equals("reset")) {
try {
targetSdkVersion = Integer.parseInt(getNextArgRequired());
} catch (NumberFormatException e) {
pw.println("Invalid targetSdkVersion!");
return -1;
} }
long changeId; }
} else {
String changeIdString = getNextArgRequired(); String changeIdString = getNextArgRequired();
try { try {
changeId = Long.parseLong(changeIdString); changeId = Long.parseLong(changeIdString);
@@ -2948,8 +2957,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println("Unknown or invalid change: '" + changeIdString + "'."); pw.println("Unknown or invalid change: '" + changeIdString + "'.");
return -1; return -1;
} }
}
String packageName = getNextArgRequired(); String packageName = getNextArgRequired();
if (!platformCompat.isKnownChangeId(changeId)) { if (!toggleAll && !platformCompat.isKnownChangeId(changeId)) {
pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it" pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
+ " could have no effect."); + " could have no effect.");
} }
@@ -2958,22 +2968,49 @@ final class ActivityManagerShellCommand extends ShellCommand {
try { try {
switch (toggleValue) { switch (toggleValue) {
case "enable": case "enable":
if (toggleAll) {
int numChanges = platformCompat.enableTargetSdkChanges(packageName,
targetSdkVersion);
if (numChanges == 0) {
pw.println("No changes were enabled.");
return -1;
}
pw.println("Enabled " + numChanges + " changes gated by targetSdkVersion "
+ targetSdkVersion + " for " + packageName + ".");
} else {
enabled.add(changeId); enabled.add(changeId);
CompatibilityChangeConfig overrides = CompatibilityChangeConfig overrides =
new CompatibilityChangeConfig( new CompatibilityChangeConfig(
new Compatibility.ChangeConfig(enabled, disabled)); new Compatibility.ChangeConfig(enabled, disabled));
platformCompat.setOverrides(overrides, packageName); platformCompat.setOverrides(overrides, packageName);
pw.println("Enabled change " + changeId + " for " + packageName + "."); pw.println("Enabled change " + changeId + " for " + packageName + ".");
}
return 0; return 0;
case "disable": case "disable":
if (toggleAll) {
int numChanges = platformCompat.disableTargetSdkChanges(packageName,
targetSdkVersion);
if (numChanges == 0) {
pw.println("No changes were disabled.");
return -1;
}
pw.println("Disabled " + numChanges + " changes gated by targetSdkVersion "
+ targetSdkVersion + " for " + packageName + ".");
} else {
disabled.add(changeId); disabled.add(changeId);
overrides = CompatibilityChangeConfig overrides =
new CompatibilityChangeConfig( new CompatibilityChangeConfig(
new Compatibility.ChangeConfig(enabled, disabled)); new Compatibility.ChangeConfig(enabled, disabled));
platformCompat.setOverrides(overrides, packageName); platformCompat.setOverrides(overrides, packageName);
pw.println("Disabled change " + changeId + " for " + packageName + "."); pw.println("Disabled change " + changeId + " for " + packageName + ".");
}
return 0; return 0;
case "reset": case "reset":
if (toggleAll) {
platformCompat.clearOverrides(packageName);
pw.println("Reset all changes for " + packageName + " to default value.");
return 0;
}
if (platformCompat.clearOverride(changeId, packageName)) { if (platformCompat.clearOverride(changeId, packageName)) {
pw.println("Reset change " + changeId + " for " + packageName pw.println("Reset change " + changeId + " for " + packageName
+ " to default value."); + " to default value.");
@@ -3304,6 +3341,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>"); pw.println(" enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>."); pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>.");
pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect)."); pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
pw.println(" enable-all|disable-all <targetSdkVersion> <PACKAGE_NAME");
pw.println(" Toggles all changes that are gated by <targetSdkVersion>.");
pw.println(" reset-all <PACKAGE_NAME>"); pw.println(" reset-all <PACKAGE_NAME>");
pw.println(" Removes all existing overrides for all changes for "); pw.println(" Removes all existing overrides for all changes for ");
pw.println(" <PACKAGE_NAME> (back to default behaviour)."); pw.println(" <PACKAGE_NAME> (back to default behaviour).");

View File

@@ -314,6 +314,63 @@ final class CompatConfig {
} }
} }
private long[] getAllowedChangesAfterTargetSdkForPackage(String packageName,
int targetSdkVersion)
throws RemoteException {
LongArray allowed = new LongArray();
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
try {
CompatChange change = mChanges.valueAt(i);
if (change.getEnableAfterTargetSdk() != targetSdkVersion) {
continue;
}
OverrideAllowedState allowedState =
mOverrideValidator.getOverrideAllowedState(change.getId(),
packageName);
if (allowedState.state == OverrideAllowedState.ALLOWED) {
allowed.add(change.getId());
}
} catch (RemoteException e) {
// Should never occur, since validator is in the same process.
throw new RuntimeException("Unable to call override validator!", e);
}
}
}
return allowed.toArray();
}
/**
* Enables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
* {@param packageName}.
*
* @return The number of changes that were toggled.
*/
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
throws RemoteException {
long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
for (long changeId : changes) {
addOverride(changeId, packageName, true);
}
return changes.length;
}
/**
* Disables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
* {@param packageName}.
*
* @return The number of changes that were toggled.
*/
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
throws RemoteException {
long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
for (long changeId : changes) {
addOverride(changeId, packageName, false);
}
return changes.length;
}
boolean registerListener(long changeId, CompatChange.ChangeListener listener) { boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
boolean alreadyKnown = true; boolean alreadyKnown = true;
synchronized (mChanges) { synchronized (mChanges) {

View File

@@ -165,6 +165,26 @@ public class PlatformCompat extends IPlatformCompat.Stub {
mCompatConfig.addOverrides(overrides, packageName); mCompatConfig.addOverrides(overrides, packageName);
} }
@Override
public int enableTargetSdkChanges(String packageName, int targetSdkVersion)
throws RemoteException, SecurityException {
checkCompatChangeOverridePermission();
int numChanges = mCompatConfig.enableTargetSdkChangesForPackage(packageName,
targetSdkVersion);
killPackage(packageName);
return numChanges;
}
@Override
public int disableTargetSdkChanges(String packageName, int targetSdkVersion)
throws RemoteException, SecurityException {
checkCompatChangeOverridePermission();
int numChanges = mCompatConfig.disableTargetSdkChangesForPackage(packageName,
targetSdkVersion);
killPackage(packageName);
return numChanges;
}
@Override @Override
public void clearOverrides(String packageName) throws RemoteException, SecurityException { public void clearOverrides(String packageName) throws RemoteException, SecurityException {
checkCompatChangeOverridePermission(); checkCompatChangeOverridePermission();

View File

@@ -266,6 +266,49 @@ public class CompatConfigTest {
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue(); assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
} }
@Test
public void testEnableTargetSdkChangesForPackage() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithId(1L)
.addDisabledChangeWithId(2L)
.addTargetSdkChangeWithId(3, 3L)
.addTargetSdkChangeWithId(4, 4L)
.build();
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("foo.bar")
.withTargetSdk(2)
.build();
assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse();
assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue();
assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
}
@Test
public void testDisableTargetSdkChangesForPackage() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithId(1L)
.addDisabledChangeWithId(2L)
.addTargetSdkChangeWithId(3, 3L)
.addTargetSdkChangeWithId(4, 4L)
.build();
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("foo.bar")
.withTargetSdk(2)
.build();
assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue();
assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
assertThat(compatConfig.disableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse();
assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
}
@Test @Test
public void testLookupChangeId() throws Exception { public void testLookupChangeId() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)