Merge "Add option to toggle all changes" am: 77d832b12d am: 88eb11eab5 am: e2093c1695

Change-Id: I10ca066b5180e3642258d742230e403f157f1149
This commit is contained in:
Automerger Merge Worker
2020-03-10 13:10:26 +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,25 +2931,35 @@ 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"));
long changeId; toggleAll = true;
String changeIdString = getNextArgRequired(); if (!toggleValue.equals("reset")) {
try { try {
changeId = Long.parseLong(changeIdString); targetSdkVersion = Integer.parseInt(getNextArgRequired());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
changeId = platformCompat.lookupChangeId(changeIdString); pw.println("Invalid targetSdkVersion!");
} return -1;
if (changeId == -1) { }
pw.println("Unknown or invalid change: '" + changeIdString + "'."); }
return -1; } else {
String changeIdString = getNextArgRequired();
try {
changeId = Long.parseLong(changeIdString);
} catch (NumberFormatException e) {
changeId = platformCompat.lookupChangeId(changeIdString);
}
if (changeId == -1) {
pw.println("Unknown or invalid change: '" + changeIdString + "'.");
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":
enabled.add(changeId); if (toggleAll) {
CompatibilityChangeConfig overrides = int numChanges = platformCompat.enableTargetSdkChanges(packageName,
new CompatibilityChangeConfig( targetSdkVersion);
new Compatibility.ChangeConfig(enabled, disabled)); if (numChanges == 0) {
platformCompat.setOverrides(overrides, packageName); pw.println("No changes were enabled.");
pw.println("Enabled change " + changeId + " for " + packageName + "."); return -1;
}
pw.println("Enabled " + numChanges + " changes gated by targetSdkVersion "
+ targetSdkVersion + " for " + packageName + ".");
} else {
enabled.add(changeId);
CompatibilityChangeConfig overrides =
new CompatibilityChangeConfig(
new Compatibility.ChangeConfig(enabled, disabled));
platformCompat.setOverrides(overrides, packageName);
pw.println("Enabled change " + changeId + " for " + packageName + ".");
}
return 0; return 0;
case "disable": case "disable":
disabled.add(changeId); if (toggleAll) {
overrides = int numChanges = platformCompat.disableTargetSdkChanges(packageName,
new CompatibilityChangeConfig( targetSdkVersion);
new Compatibility.ChangeConfig(enabled, disabled)); if (numChanges == 0) {
platformCompat.setOverrides(overrides, packageName); pw.println("No changes were disabled.");
pw.println("Disabled change " + changeId + " for " + packageName + "."); return -1;
}
pw.println("Disabled " + numChanges + " changes gated by targetSdkVersion "
+ targetSdkVersion + " for " + packageName + ".");
} else {
disabled.add(changeId);
CompatibilityChangeConfig overrides =
new CompatibilityChangeConfig(
new Compatibility.ChangeConfig(enabled, disabled));
platformCompat.setOverrides(overrides, 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)