summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author tomnatan <tomnatan@google.com> 2021-02-24 17:45:03 +0000
committer tomnatan <tomnatan@google.com> 2021-03-01 18:43:26 +0000
commit93ca0db1cafbbb60de6b4fb1a01954bdaa2e3e9f (patch)
tree966d778f33e8053efb9000ac054163db513b7c11
parent6c80c464e0b6d2c9fdc1904b14aa34e6ec17db0a (diff)
Add support for loading a static overrides file located in /product.
Note that the dynamic overrides file in the /data/misc/appcompat will be loaded after the static file is loaded and take precedence over it (overrides in the dynamic file will override corresponding ones in the static file). This static file will be used to inject hard coded per app configuration. Bug: 180396167 Test: atest FrameworksServicesTests:CompatConfigTest Change-Id: I73569744e718274255885d270ab8285956647f4c
-rw-r--r--services/core/java/com/android/server/compat/CompatChange.java87
-rw-r--r--services/core/java/com/android/server/compat/CompatConfig.java35
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java131
3 files changed, 187 insertions, 66 deletions
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index df83df9a73fb..5cf478a3ef1f 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -80,6 +80,15 @@ public final class CompatChange extends CompatibilityChangeInfo {
}
/**
+ * @param change an object generated by services/core/xsd/platform-compat-config.xsd
+ */
+ public CompatChange(Change change) {
+ this(change.getId(), change.getName(), change.getEnableAfterTargetSdk(),
+ change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(),
+ change.getDescription(), change.getOverridable());
+ }
+
+ /**
* @param changeId Unique ID for the change. See {@link android.compat.Compatibility}.
* @param name Short descriptive name.
* @param enableAfterTargetSdk {@code targetSdkVersion} restriction. See {@link EnabledAfter};
@@ -93,15 +102,10 @@ public final class CompatChange extends CompatibilityChangeInfo {
boolean overridable) {
super(changeId, name, enableAfterTargetSdk, enableSinceTargetSdk, disabled, loggingOnly,
description, overridable);
- }
- /**
- * @param change an object generated by services/core/xsd/platform-compat-config.xsd
- */
- public CompatChange(Change change) {
- super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(),
- change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(),
- change.getDescription(), change.getOverridable());
+ // Initialize override maps.
+ mEvaluatedOverrides = new HashMap<>();
+ mRawOverrides = new HashMap<>();
}
void registerListener(ChangeListener listener) {
@@ -127,18 +131,13 @@ public final class CompatChange extends CompatibilityChangeInfo {
throw new IllegalArgumentException(
"Can't add overrides for a logging only change " + toString());
}
- if (mEvaluatedOverrides == null) {
- mEvaluatedOverrides = new HashMap<>();
- }
mEvaluatedOverrides.put(pname, enabled);
notifyListener(pname);
}
private void removePackageOverrideInternal(String pname) {
- if (mEvaluatedOverrides != null) {
- if (mEvaluatedOverrides.remove(pname) != null) {
- notifyListener(pname);
- }
+ if (mEvaluatedOverrides.remove(pname) != null) {
+ notifyListener(pname);
}
}
@@ -157,9 +156,6 @@ public final class CompatChange extends CompatibilityChangeInfo {
throw new IllegalArgumentException(
"Can't add overrides for a logging only change " + toString());
}
- if (mRawOverrides == null) {
- mRawOverrides = new HashMap<>();
- }
mRawOverrides.put(packageName, override);
recheckOverride(packageName, allowedState, context);
}
@@ -212,7 +208,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
}
boolean hasPackageOverride(String pname) {
- return mRawOverrides != null && mRawOverrides.containsKey(pname);
+ return mRawOverrides.containsKey(pname);
}
/**
* Remove any package override for the given package name, restoring the default behaviour.
@@ -223,7 +219,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
*/
boolean removePackageOverride(String pname, OverrideAllowedState allowedState,
Context context) {
- if (mRawOverrides != null && (mRawOverrides.remove(pname) != null)) {
+ if (mRawOverrides.remove(pname) != null) {
recheckOverride(pname, allowedState, context);
return true;
}
@@ -241,7 +237,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
if (app == null) {
return defaultValue();
}
- if (mEvaluatedOverrides != null && mEvaluatedOverrides.containsKey(app.packageName)) {
+ if (mEvaluatedOverrides.containsKey(app.packageName)) {
return mEvaluatedOverrides.get(app.packageName);
}
if (getDisabled()) {
@@ -289,7 +285,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
* @return true if there is such override
*/
private boolean hasOverride(String packageName) {
- return mEvaluatedOverrides != null && mEvaluatedOverrides.containsKey(packageName);
+ return mEvaluatedOverrides.containsKey(packageName);
}
/**
@@ -298,20 +294,15 @@ public final class CompatChange extends CompatibilityChangeInfo {
* @return true if there is such a deferred override
*/
private boolean hasRawOverride(String packageName) {
- return mRawOverrides != null && mRawOverrides.containsKey(packageName);
+ return mRawOverrides.containsKey(packageName);
}
- void loadOverrides(ChangeOverrides changeOverrides) {
- if (mRawOverrides == null) {
- mRawOverrides = new HashMap<>();
- }
+ void clearOverrides() {
mRawOverrides.clear();
-
- if (mEvaluatedOverrides == null) {
- mEvaluatedOverrides = new HashMap<>();
- }
mEvaluatedOverrides.clear();
+ }
+ void loadOverrides(ChangeOverrides changeOverrides) {
// Load deferred overrides for backwards compatibility
if (changeOverrides.getDeferred() != null) {
for (OverrideValue override : changeOverrides.getDeferred().getOverrideValue()) {
@@ -345,34 +336,30 @@ public final class CompatChange extends CompatibilityChangeInfo {
}
ChangeOverrides saveOverrides() {
- if (mRawOverrides == null || mRawOverrides.isEmpty()) {
+ if (mRawOverrides.isEmpty()) {
return null;
}
ChangeOverrides changeOverrides = new ChangeOverrides();
changeOverrides.setChangeId(getId());
ChangeOverrides.Raw rawOverrides = new ChangeOverrides.Raw();
List<RawOverrideValue> rawList = rawOverrides.getRawOverrideValue();
- if (mRawOverrides != null) {
- for (Map.Entry<String, PackageOverride> entry : mRawOverrides.entrySet()) {
- RawOverrideValue override = new RawOverrideValue();
- override.setPackageName(entry.getKey());
- override.setMinVersionCode(entry.getValue().getMinVersionCode());
- override.setMaxVersionCode(entry.getValue().getMaxVersionCode());
- override.setEnabled(entry.getValue().getEnabled());
- rawList.add(override);
- }
+ for (Map.Entry<String, PackageOverride> entry : mRawOverrides.entrySet()) {
+ RawOverrideValue override = new RawOverrideValue();
+ override.setPackageName(entry.getKey());
+ override.setMinVersionCode(entry.getValue().getMinVersionCode());
+ override.setMaxVersionCode(entry.getValue().getMaxVersionCode());
+ override.setEnabled(entry.getValue().getEnabled());
+ rawList.add(override);
}
changeOverrides.setRaw(rawOverrides);
ChangeOverrides.Validated validatedOverrides = new ChangeOverrides.Validated();
List<OverrideValue> validatedList = validatedOverrides.getOverrideValue();
- if (mEvaluatedOverrides != null) {
- for (Map.Entry<String, Boolean> entry : mEvaluatedOverrides.entrySet()) {
- OverrideValue override = new OverrideValue();
- override.setPackageName(entry.getKey());
- override.setEnabled(entry.getValue());
- validatedList.add(override);
- }
+ for (Map.Entry<String, Boolean> entry : mEvaluatedOverrides.entrySet()) {
+ OverrideValue override = new OverrideValue();
+ override.setPackageName(entry.getKey());
+ override.setEnabled(entry.getValue());
+ validatedList.add(override);
}
changeOverrides.setValidated(validatedOverrides);
return changeOverrides;
@@ -394,10 +381,10 @@ public final class CompatChange extends CompatibilityChangeInfo {
if (getLoggingOnly()) {
sb.append("; loggingOnly");
}
- if (mEvaluatedOverrides != null && mEvaluatedOverrides.size() > 0) {
+ if (!mEvaluatedOverrides.isEmpty()) {
sb.append("; packageOverrides=").append(mEvaluatedOverrides);
}
- if (mRawOverrides != null && mRawOverrides.size() > 0) {
+ if (!mRawOverrides.isEmpty()) {
sb.append("; rawOverrides=").append(mRawOverrides);
}
if (getOverridable()) {
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 66a652053857..2c053b421904 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -67,6 +67,7 @@ final class CompatConfig {
private static final String TAG = "CompatConfig";
private static final String APP_COMPAT_DATA_DIR = "/data/misc/appcompat";
+ private static final String STATIC_OVERRIDES_PRODUCT_DIR = "/product/etc/appcompat";
private static final String OVERRIDES_FILE = "compat_framework_overrides.xml";
@GuardedBy("mChanges")
@@ -94,8 +95,7 @@ final class CompatConfig {
config.initConfigFromLib(Environment.buildPath(
apex.apexDirectory, "etc", "compatconfig"));
}
- File overridesFile = new File(APP_COMPAT_DATA_DIR, OVERRIDES_FILE);
- config.initOverrides(overridesFile);
+ config.initOverrides();
config.invalidateCache();
return config;
}
@@ -525,10 +525,34 @@ final class CompatConfig {
}
}
- void initOverrides(File overridesFile) {
+ private void initOverrides() {
+ initOverrides(new File(APP_COMPAT_DATA_DIR, OVERRIDES_FILE),
+ new File(STATIC_OVERRIDES_PRODUCT_DIR, OVERRIDES_FILE));
+ }
+
+ @VisibleForTesting
+ void initOverrides(File dynamicOverridesFile, File staticOverridesFile) {
+ // Clear overrides from all changes before loading.
+ synchronized (mChanges) {
+ for (int i = 0; i < mChanges.size(); ++i) {
+ mChanges.valueAt(i).clearOverrides();
+ }
+ }
+
+ loadOverrides(staticOverridesFile);
+
+ mOverridesFile = dynamicOverridesFile;
+ loadOverrides(dynamicOverridesFile);
+
+ if (staticOverridesFile.exists()) {
+ // Only save overrides if there is a static overrides file.
+ saveOverrides();
+ }
+ }
+
+ private void loadOverrides(File overridesFile) {
if (!overridesFile.exists()) {
- mOverridesFile = overridesFile;
- // There have not been any overrides added yet.
+ // Overrides file doesn't exist.
return;
}
@@ -548,7 +572,6 @@ final class CompatConfig {
Slog.w(TAG, "Error processing " + overridesFile + " " + e.toString());
return;
}
- mOverridesFile = overridesFile;
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 8b0e948579fb..b6b6932c4a93 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -602,12 +602,12 @@ public class CompatConfigTest {
.addEnableSinceSdkChangeWithId(2, 2L)
.build();
compatConfig.forceNonDebuggableFinalForTest(true);
- compatConfig.initOverrides(overridesFile);
+ compatConfig.initOverrides(overridesFile, new File(""));
when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt()))
.thenReturn(ApplicationInfoBuilder.create()
- .withPackageName("foo.bar")
- .debuggable()
- .build());
+ .withPackageName("foo.bar")
+ .debuggable()
+ .build());
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
.thenThrow(new NameNotFoundException());
@@ -649,7 +649,7 @@ public class CompatConfigTest {
.addEnableSinceSdkChangeWithId(2, 2L)
.build();
compatConfig.forceNonDebuggableFinalForTest(true);
- compatConfig.initOverrides(overridesFile);
+ compatConfig.initOverrides(overridesFile, new File(""));
compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L,
new PackageOverride.Builder()
@@ -673,11 +673,11 @@ public class CompatConfigTest {
}
@Test
- public void testLoadOverridesRaw() throws Exception {
+ public void testInitOverridesRaw() throws Exception {
File tempDir = createTempDir();
File overridesFile = new File(tempDir, "overrides.xml");
// Change 1 is enabled for foo.bar (validated)
- // Change 2 is disabled for bar.baz (deferred)
+ // Change 2 is disabled for bar.baz (raw)
String xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<overrides>\n"
+ " <change-overrides changeId=\"1\">\n"
@@ -709,7 +709,7 @@ public class CompatConfigTest {
.addEnableSinceSdkChangeWithId(2, 2L)
.build();
compatConfig.forceNonDebuggableFinalForTest(true);
- compatConfig.initOverrides(overridesFile);
+ compatConfig.initOverrides(overridesFile, new File(""));
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("foo.bar")
.withVersionCode(100L)
@@ -728,7 +728,7 @@ public class CompatConfigTest {
}
@Test
- public void testLoadOverridesDeferred() throws Exception {
+ public void testInitOverridesDeferred() throws Exception {
File tempDir = createTempDir();
File overridesFile = new File(tempDir, "overrides.xml");
// Change 1 is enabled for foo.bar (validated)
@@ -754,7 +754,7 @@ public class CompatConfigTest {
.addEnableSinceSdkChangeWithId(2, 2L)
.build();
compatConfig.forceNonDebuggableFinalForTest(true);
- compatConfig.initOverrides(overridesFile);
+ compatConfig.initOverrides(overridesFile, new File(""));
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("foo.bar")
.debuggable()
@@ -767,4 +767,115 @@ public class CompatConfigTest {
assertThat(compatConfig.isChangeEnabled(1L, applicationInfo)).isTrue();
assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse();
}
+
+ @Test
+ public void testInitOverridesWithStaticFile() throws Exception {
+ File tempDir = createTempDir();
+ File dynamicOverridesFile = new File(tempDir, "dynamic_overrides.xml");
+ File staticOverridesFile = new File(tempDir, "static_overrides.xml");
+ // Change 1 is enabled for foo.bar (raw)
+ // Change 2 is disabled for bar.baz (raw)
+ String dynamicXmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ + "<overrides>"
+ + "<change-overrides changeId=\"1\">"
+ + "<raw>"
+ + " <raw-override-value packageName=\"foo.bar\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + "</raw>"
+ + "</change-overrides>"
+ + "<change-overrides changeId=\"2\">"
+ + "<raw>"
+ + " <raw-override-value packageName=\"bar.baz\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n"
+ + " </raw-override-value>\n"
+ + "</raw>"
+ + "</change-overrides>"
+ + "</overrides>";
+ writeToFile(tempDir, "dynamic_overrides.xml", dynamicXmlData);
+ // Change 2 is enabled for foo.bar and bar.baz (raw)
+ // Change 3 is enabled for bar.baz (raw)
+ String staticXmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ + "<overrides>"
+ + "<change-overrides changeId=\"2\">"
+ + "<raw>"
+ + " <raw-override-value packageName=\"foo.bar\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + " <raw-override-value packageName=\"bar.baz\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + "</raw>"
+ + "</change-overrides>"
+ + "<change-overrides changeId=\"3\">"
+ + "<raw>"
+ + " <raw-override-value packageName=\"bar.baz\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + "</raw>"
+ + "</change-overrides>"
+ + "</overrides>";
+ writeToFile(tempDir, "static_overrides.xml", staticXmlData);
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1L)
+ .addDisabledChangeWithId(2L)
+ .addDisabledChangeWithId(3L)
+ .build();
+ compatConfig.forceNonDebuggableFinalForTest(true);
+ // Adding an override that will be cleared after initOverrides is called.
+ compatConfig.addOverride(1L, "bar.baz", true);
+ compatConfig.initOverrides(dynamicOverridesFile, staticOverridesFile);
+ when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt()))
+ .thenThrow(new NameNotFoundException());
+ when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
+ .thenThrow(new NameNotFoundException());
+
+ assertThat(compatConfig.willChangeBeEnabled(1L, "foo.bar")).isTrue();
+ assertThat(compatConfig.willChangeBeEnabled(2L, "foo.bar")).isTrue();
+ assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse();
+ assertThat(compatConfig.willChangeBeEnabled(3L, "bar.baz")).isTrue();
+ assertThat(readFile(dynamicOverridesFile))
+ .isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<overrides>\n"
+ + " <change-overrides changeId=\"1\">\n"
+ + " <validated>\n"
+ + " </validated>\n"
+ + " <raw>\n"
+ + " <raw-override-value packageName=\"foo.bar\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + " </raw>\n"
+ + " </change-overrides>\n"
+ + " <change-overrides changeId=\"2\">\n"
+ + " <validated>\n"
+ + " </validated>\n"
+ + " <raw>\n"
+ + " <raw-override-value packageName=\"foo.bar\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + " <raw-override-value packageName=\"bar.baz\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n"
+ + " </raw-override-value>\n"
+ + " </raw>\n"
+ + " </change-overrides>\n"
+ + " <change-overrides changeId=\"3\">\n"
+ + " <validated>\n"
+ + " </validated>\n"
+ + " <raw>\n"
+ + " <raw-override-value packageName=\"bar.baz\" "
+ + "minVersionCode=\"-9223372036854775808\" "
+ + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n"
+ + " </raw-override-value>\n"
+ + " </raw>\n"
+ + " </change-overrides>\n"
+ + "</overrides>\n");
+ }
}