Merge "Skip unknown change IDs when adding/removing overrides on release builds" into sc-v2-dev
This commit is contained in:
@@ -222,9 +222,16 @@ final class CompatConfig {
|
|||||||
*
|
*
|
||||||
* @param overrides list of overrides to default changes config.
|
* @param overrides list of overrides to default changes config.
|
||||||
* @param packageName app for which the overrides will be applied.
|
* @param packageName app for which the overrides will be applied.
|
||||||
|
* @param skipUnknownChangeIds whether to skip unknown change IDs in {@code overrides}.
|
||||||
*/
|
*/
|
||||||
synchronized void addOverrides(CompatibilityOverrideConfig overrides, String packageName) {
|
synchronized void addPackageOverrides(CompatibilityOverrideConfig overrides,
|
||||||
|
String packageName, boolean skipUnknownChangeIds) {
|
||||||
for (Long changeId : overrides.overrides.keySet()) {
|
for (Long changeId : overrides.overrides.keySet()) {
|
||||||
|
if (skipUnknownChangeIds && !isKnownChangeId(changeId)) {
|
||||||
|
Slog.w(TAG, "Trying to add overrides for unknown Change ID " + changeId + ". "
|
||||||
|
+ "Skipping Change ID.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
|
addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
|
||||||
}
|
}
|
||||||
saveOverrides();
|
saveOverrides();
|
||||||
@@ -335,7 +342,8 @@ final class CompatConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
|
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
|
||||||
* {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
|
* {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain
|
||||||
|
* package.
|
||||||
*
|
*
|
||||||
* <p>This restores the default behaviour for the given app.
|
* <p>This restores the default behaviour for the given app.
|
||||||
*
|
*
|
||||||
@@ -356,7 +364,8 @@ final class CompatConfig {
|
|||||||
/**
|
/**
|
||||||
* Removes overrides whose change ID is specified in {@code overridesToRemove} that were
|
* Removes overrides whose change ID is specified in {@code overridesToRemove} that were
|
||||||
* previously added via {@link #addOverride(long, String, boolean)} or
|
* previously added via {@link #addOverride(long, String, boolean)} or
|
||||||
* {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
|
* {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain
|
||||||
|
* package.
|
||||||
*
|
*
|
||||||
* <p>This restores the default behaviour for the given change IDs and app.
|
* <p>This restores the default behaviour for the given change IDs and app.
|
||||||
*
|
*
|
||||||
@@ -367,6 +376,11 @@ final class CompatConfig {
|
|||||||
String packageName) {
|
String packageName) {
|
||||||
boolean shouldInvalidateCache = false;
|
boolean shouldInvalidateCache = false;
|
||||||
for (Long changeId : overridesToRemove.changeIds) {
|
for (Long changeId : overridesToRemove.changeIds) {
|
||||||
|
if (!isKnownChangeId(changeId)) {
|
||||||
|
Slog.w(TAG, "Trying to remove overrides for unknown Change ID " + changeId + ". "
|
||||||
|
+ "Skipping Change ID.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
shouldInvalidateCache |= removeOverrideUnsafe(changeId, packageName);
|
shouldInvalidateCache |= removeOverrideUnsafe(changeId, packageName);
|
||||||
}
|
}
|
||||||
if (shouldInvalidateCache) {
|
if (shouldInvalidateCache) {
|
||||||
|
|||||||
@@ -205,7 +205,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
|
overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName);
|
mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap),
|
||||||
|
packageName, /* skipUnknownChangeIds */ false);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +221,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
|
overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName);
|
mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap),
|
||||||
|
packageName, /* skipUnknownChangeIds */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -229,7 +231,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
// TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
|
// TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
|
||||||
checkCompatChangeOverrideOverridablePermission();
|
checkCompatChangeOverrideOverridablePermission();
|
||||||
checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
|
checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
|
||||||
mCompatConfig.addOverrides(overrides, packageName);
|
mCompatConfig.addPackageOverrides(overrides, packageName, /* skipUnknownChangeIds= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -435,7 +437,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) {
|
private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) {
|
||||||
for (Long changeId : changeIds) {
|
for (Long changeId : changeIds) {
|
||||||
if (!mCompatConfig.isOverridable(changeId)) {
|
if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) {
|
||||||
throw new SecurityException("Only change ids marked as Overridable can be "
|
throw new SecurityException("Only change ids marked as Overridable can be "
|
||||||
+ "overridden.");
|
+ "overridden.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,9 +265,10 @@ public class CompatConfigTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInstallerCanSetOverrides() throws Exception {
|
public void testInstallerCanAddOverrides() throws Exception {
|
||||||
final long disabledChangeId1 = 1234L;
|
final long disabledChangeId1 = 1234L;
|
||||||
final long disabledChangeId2 = 1235L;
|
final long disabledChangeId2 = 1235L;
|
||||||
|
final long unknownChangeId = 1236L;
|
||||||
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
||||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||||
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
||||||
@@ -284,19 +285,25 @@ public class CompatConfigTest {
|
|||||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||||
|
Map<Long, PackageOverride> overrides = new HashMap<>();
|
||||||
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(
|
overrides.put(disabledChangeId1, new PackageOverride.Builder()
|
||||||
Collections.singletonMap(disabledChangeId1,
|
|
||||||
new PackageOverride.Builder()
|
|
||||||
.setMaxVersionCode(99L)
|
.setMaxVersionCode(99L)
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.build()));
|
.build());
|
||||||
|
// Adding an unknown change ID to make sure it's skipped if skipUnknownChangeIds is true.
|
||||||
|
overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build());
|
||||||
|
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
||||||
|
|
||||||
compatConfig.addOverrides(config, "com.some.package");
|
compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */
|
||||||
|
true);
|
||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
|
||||||
|
// Making sure the unknown change ID is still unknown and isChangeEnabled returns true.
|
||||||
|
assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse();
|
||||||
|
assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPreventInstallerSetNonOverridable() throws Exception {
|
public void testPreventInstallerSetNonOverridable() throws Exception {
|
||||||
final long disabledChangeId1 = 1234L;
|
final long disabledChangeId1 = 1234L;
|
||||||
@@ -326,13 +333,46 @@ public class CompatConfigTest {
|
|||||||
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
||||||
|
|
||||||
assertThrows(SecurityException.class,
|
assertThrows(SecurityException.class,
|
||||||
() -> compatConfig.addOverrides(config, "com.some.package")
|
() -> compatConfig.addPackageOverrides(config, "com.some.package",
|
||||||
|
/* skipUnknownChangeIds */ true)
|
||||||
);
|
);
|
||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
|
||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId3, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId3, applicationInfo)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCanAddOverridesForUnknownChangeIdOnDebugBuild() throws Exception {
|
||||||
|
final long disabledChangeId = 1234L;
|
||||||
|
final long unknownChangeId = 1235L;
|
||||||
|
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
||||||
|
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||||
|
.addDisabledChangeWithId(disabledChangeId)
|
||||||
|
.build();
|
||||||
|
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||||
|
.withPackageName("com.some.package")
|
||||||
|
.build();
|
||||||
|
PackageManager packageManager = mock(PackageManager.class);
|
||||||
|
when(mContext.getPackageManager()).thenReturn(packageManager);
|
||||||
|
when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
|
||||||
|
.thenReturn(applicationInfo);
|
||||||
|
|
||||||
|
when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
|
||||||
|
Map<Long, PackageOverride> overrides = new HashMap<>();
|
||||||
|
overrides.put(disabledChangeId, new PackageOverride.Builder().setEnabled(true).build());
|
||||||
|
// Adding an unknown change ID to make sure it isn't skipped if skipUnknownChangeIds is
|
||||||
|
// false.
|
||||||
|
overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build());
|
||||||
|
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
||||||
|
|
||||||
|
compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */
|
||||||
|
false);
|
||||||
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId, applicationInfo)).isTrue();
|
||||||
|
// Making sure the unknown change ID is now known and has an override.
|
||||||
|
assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isTrue();
|
||||||
|
assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
|
public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
|
||||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||||
@@ -377,7 +417,8 @@ public class CompatConfigTest {
|
|||||||
.setMaxVersionCode(99L)
|
.setMaxVersionCode(99L)
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.build()));
|
.build()));
|
||||||
compatConfig.addOverrides(config, "com.installed.foo");
|
compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */
|
||||||
|
true);
|
||||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
||||||
|
|
||||||
// Add override that does include the installed app version
|
// Add override that does include the installed app version
|
||||||
@@ -388,7 +429,8 @@ public class CompatConfigTest {
|
|||||||
.setMaxVersionCode(100L)
|
.setMaxVersionCode(100L)
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.build()));
|
.build()));
|
||||||
compatConfig.addOverrides(config, "com.installed.foo");
|
compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */
|
||||||
|
true);
|
||||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +453,8 @@ public class CompatConfigTest {
|
|||||||
.setMaxVersionCode(99L)
|
.setMaxVersionCode(99L)
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.build()));
|
.build()));
|
||||||
compatConfig.addOverrides(config, "com.notinstalled.foo");
|
compatConfig.addPackageOverrides(config, "com.notinstalled.foo", /* skipUnknownChangeIds */
|
||||||
|
true);
|
||||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
||||||
|
|
||||||
// Pretend the app is now installed.
|
// Pretend the app is now installed.
|
||||||
@@ -557,6 +600,7 @@ public class CompatConfigTest {
|
|||||||
final long disabledChangeId1 = 1234L;
|
final long disabledChangeId1 = 1234L;
|
||||||
final long disabledChangeId2 = 1235L;
|
final long disabledChangeId2 = 1235L;
|
||||||
final long enabledChangeId = 1236L;
|
final long enabledChangeId = 1236L;
|
||||||
|
final long unknownChangeId = 1237L;
|
||||||
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
||||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||||
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
||||||
@@ -583,6 +627,8 @@ public class CompatConfigTest {
|
|||||||
Set<Long> overridesToRemove = new HashSet<>();
|
Set<Long> overridesToRemove = new HashSet<>();
|
||||||
overridesToRemove.add(disabledChangeId1);
|
overridesToRemove.add(disabledChangeId1);
|
||||||
overridesToRemove.add(enabledChangeId);
|
overridesToRemove.add(enabledChangeId);
|
||||||
|
// Adding an unknown change ID to make sure it's skipped.
|
||||||
|
overridesToRemove.add(unknownChangeId);
|
||||||
CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
|
CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
|
||||||
overridesToRemove);
|
overridesToRemove);
|
||||||
|
|
||||||
@@ -590,6 +636,8 @@ public class CompatConfigTest {
|
|||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse();
|
||||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
|
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
|
||||||
assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isTrue();
|
assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isTrue();
|
||||||
|
// Making sure the unknown change ID is still unknown.
|
||||||
|
assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -797,18 +845,18 @@ public class CompatConfigTest {
|
|||||||
.build());
|
.build());
|
||||||
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
|
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
|
||||||
.thenThrow(new NameNotFoundException());
|
.thenThrow(new NameNotFoundException());
|
||||||
compatConfig.addOverrides(
|
compatConfig.addPackageOverrides(
|
||||||
new CompatibilityOverrideConfig(
|
new CompatibilityOverrideConfig(
|
||||||
Collections.singletonMap(
|
Collections.singletonMap(
|
||||||
1L,
|
1L,
|
||||||
new PackageOverride.Builder().setEnabled(true).build())),
|
new PackageOverride.Builder().setEnabled(true).build())),
|
||||||
"foo.bar");
|
"foo.bar", /* skipUnknownChangeIds */ true);
|
||||||
compatConfig.addOverrides(
|
compatConfig.addPackageOverrides(
|
||||||
new CompatibilityOverrideConfig(
|
new CompatibilityOverrideConfig(
|
||||||
Collections.singletonMap(
|
Collections.singletonMap(
|
||||||
2L,
|
2L,
|
||||||
new PackageOverride.Builder().setEnabled(false).build())),
|
new PackageOverride.Builder().setEnabled(false).build())),
|
||||||
"bar.baz");
|
"bar.baz", /* skipUnknownChangeIds */ true);
|
||||||
|
|
||||||
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||||
+ "<overrides>\n"
|
+ "<overrides>\n"
|
||||||
@@ -847,12 +895,12 @@ public class CompatConfigTest {
|
|||||||
compatConfig.forceNonDebuggableFinalForTest(true);
|
compatConfig.forceNonDebuggableFinalForTest(true);
|
||||||
compatConfig.initOverrides(overridesFile, new File(""));
|
compatConfig.initOverrides(overridesFile, new File(""));
|
||||||
|
|
||||||
compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L,
|
compatConfig.addPackageOverrides(new CompatibilityOverrideConfig(
|
||||||
new PackageOverride.Builder()
|
Collections.singletonMap(1L, new PackageOverride.Builder()
|
||||||
.setMinVersionCode(99L)
|
.setMinVersionCode(99L)
|
||||||
.setMaxVersionCode(101L)
|
.setMaxVersionCode(101L)
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.build())), "foo.bar");
|
.build())), "foo.bar", /* skipUnknownChangeIds */ true);
|
||||||
|
|
||||||
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||||
+ "<overrides>\n"
|
+ "<overrides>\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user