Persist compat framework overrides across reboot
Save the compat overrides in /data/misc/appcompat/compat_framework_overrides.xml Test: atest CompatConfigTest Bug: 145509340 Change-Id: I0673087c1b78addb20b03ba6299490c2d40e39ca
This commit is contained in:
@@ -84,6 +84,7 @@ java_library_static {
|
||||
":storaged_aidl",
|
||||
":vold_aidl",
|
||||
":platform-compat-config",
|
||||
":platform-compat-overrides",
|
||||
":display-device-config",
|
||||
"java/com/android/server/EventLogTags.logtags",
|
||||
"java/com/android/server/am/EventLogTags.logtags",
|
||||
|
||||
@@ -23,8 +23,11 @@ import android.content.pm.ApplicationInfo;
|
||||
|
||||
import com.android.internal.compat.CompatibilityChangeInfo;
|
||||
import com.android.server.compat.config.Change;
|
||||
import com.android.server.compat.overrides.ChangeOverrides;
|
||||
import com.android.server.compat.overrides.OverrideValue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -253,6 +256,71 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
||||
return mDeferredOverrides != null && mDeferredOverrides.containsKey(packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a change has any package overrides.
|
||||
* @return true if the change has at least one deferred override
|
||||
*/
|
||||
boolean hasAnyPackageOverride() {
|
||||
return mDeferredOverrides != null && !mDeferredOverrides.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a change has any deferred overrides.
|
||||
* @return true if the change has at least one deferred override
|
||||
*/
|
||||
boolean hasAnyDeferredOverride() {
|
||||
return mPackageOverrides != null && !mPackageOverrides.isEmpty();
|
||||
}
|
||||
|
||||
void loadOverrides(ChangeOverrides changeOverrides) {
|
||||
if (mDeferredOverrides == null) {
|
||||
mDeferredOverrides = new HashMap<>();
|
||||
}
|
||||
mDeferredOverrides.clear();
|
||||
for (OverrideValue override : changeOverrides.getDeferred().getOverrideValue()) {
|
||||
mDeferredOverrides.put(override.getPackageName(), override.getEnabled());
|
||||
}
|
||||
|
||||
if (mPackageOverrides == null) {
|
||||
mPackageOverrides = new HashMap<>();
|
||||
}
|
||||
mPackageOverrides.clear();
|
||||
for (OverrideValue override : changeOverrides.getValidated().getOverrideValue()) {
|
||||
mPackageOverrides.put(override.getPackageName(), override.getEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
ChangeOverrides saveOverrides() {
|
||||
if (!hasAnyDeferredOverride() && !hasAnyPackageOverride()) {
|
||||
return null;
|
||||
}
|
||||
ChangeOverrides changeOverrides = new ChangeOverrides();
|
||||
changeOverrides.setChangeId(getId());
|
||||
ChangeOverrides.Deferred deferredOverrides = new ChangeOverrides.Deferred();
|
||||
List<OverrideValue> deferredList = deferredOverrides.getOverrideValue();
|
||||
if (mDeferredOverrides != null) {
|
||||
for (Map.Entry<String, Boolean> entry : mDeferredOverrides.entrySet()) {
|
||||
OverrideValue override = new OverrideValue();
|
||||
override.setPackageName(entry.getKey());
|
||||
override.setEnabled(entry.getValue());
|
||||
deferredList.add(override);
|
||||
}
|
||||
}
|
||||
changeOverrides.setDeferred(deferredOverrides);
|
||||
ChangeOverrides.Validated validatedOverrides = new ChangeOverrides.Validated();
|
||||
List<OverrideValue> validatedList = validatedOverrides.getOverrideValue();
|
||||
if (mPackageOverrides != null) {
|
||||
for (Map.Entry<String, Boolean> entry : mPackageOverrides.entrySet()) {
|
||||
OverrideValue override = new OverrideValue();
|
||||
override.setPackageName(entry.getKey());
|
||||
override.setEnabled(entry.getValue());
|
||||
validatedList.add(override);
|
||||
}
|
||||
}
|
||||
changeOverrides.setValidated(validatedOverrides);
|
||||
return changeOverrides;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("ChangeId(")
|
||||
|
||||
@@ -34,7 +34,10 @@ import com.android.internal.compat.CompatibilityChangeInfo;
|
||||
import com.android.internal.compat.IOverrideValidator;
|
||||
import com.android.internal.compat.OverrideAllowedState;
|
||||
import com.android.server.compat.config.Change;
|
||||
import com.android.server.compat.config.XmlParser;
|
||||
import com.android.server.compat.config.Config;
|
||||
import com.android.server.compat.overrides.ChangeOverrides;
|
||||
import com.android.server.compat.overrides.Overrides;
|
||||
import com.android.server.compat.overrides.XmlWriter;
|
||||
import com.android.server.pm.ApexManager;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -60,11 +63,14 @@ import javax.xml.datatype.DatatypeConfigurationException;
|
||||
final class CompatConfig {
|
||||
|
||||
private static final String TAG = "CompatConfig";
|
||||
private static final String APP_COMPAT_DATA_DIR = "/data/misc/appcompat";
|
||||
private static final String OVERRIDES_FILE = "compat_framework_overrides.xml";
|
||||
|
||||
@GuardedBy("mChanges")
|
||||
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
|
||||
|
||||
private final OverrideValidatorImpl mOverrideValidator;
|
||||
private File mOverridesFile;
|
||||
|
||||
@VisibleForTesting
|
||||
CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
||||
@@ -83,6 +89,8 @@ 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.invalidateCache();
|
||||
return config;
|
||||
}
|
||||
@@ -202,6 +210,17 @@ final class CompatConfig {
|
||||
* @throws IllegalStateException if overriding is not allowed
|
||||
*/
|
||||
boolean addOverride(long changeId, String packageName, boolean enabled) {
|
||||
boolean alreadyKnown = addOverrideUnsafe(changeId, packageName, enabled);
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
return alreadyKnown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafe version of {@link #addOverride(long, String, boolean)}.
|
||||
* It does not invalidate the cache nor save the overrides.
|
||||
*/
|
||||
private boolean addOverrideUnsafe(long changeId, String packageName, boolean enabled) {
|
||||
boolean alreadyKnown = true;
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
||||
@@ -224,7 +243,6 @@ final class CompatConfig {
|
||||
throw new IllegalStateException("Should only be able to override changes that "
|
||||
+ "are allowed or can be deferred.");
|
||||
}
|
||||
invalidateCache();
|
||||
}
|
||||
return alreadyKnown;
|
||||
}
|
||||
@@ -282,6 +300,17 @@ final class CompatConfig {
|
||||
* @return {@code true} if an override existed;
|
||||
*/
|
||||
boolean removeOverride(long changeId, String packageName) {
|
||||
boolean overrideExists = removeOverrideUnsafe(changeId, packageName);
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
return overrideExists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafe version of {@link #removeOverride(long, String)}.
|
||||
* It does not invalidate the cache nor save the overrides.
|
||||
*/
|
||||
private boolean removeOverrideUnsafe(long changeId, String packageName) {
|
||||
boolean overrideExists = false;
|
||||
synchronized (mChanges) {
|
||||
CompatChange c = mChanges.get(changeId);
|
||||
@@ -300,7 +329,6 @@ final class CompatConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
invalidateCache();
|
||||
return overrideExists;
|
||||
}
|
||||
|
||||
@@ -315,12 +343,13 @@ final class CompatConfig {
|
||||
void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
|
||||
synchronized (mChanges) {
|
||||
for (Long changeId : overrides.enabledChanges()) {
|
||||
addOverride(changeId, packageName, true);
|
||||
addOverrideUnsafe(changeId, packageName, true);
|
||||
}
|
||||
for (Long changeId : overrides.disabledChanges()) {
|
||||
addOverride(changeId, packageName, false);
|
||||
addOverrideUnsafe(changeId, packageName, false);
|
||||
|
||||
}
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
@@ -337,8 +366,9 @@ final class CompatConfig {
|
||||
synchronized (mChanges) {
|
||||
for (int i = 0; i < mChanges.size(); ++i) {
|
||||
CompatChange change = mChanges.valueAt(i);
|
||||
removeOverride(change.getId(), packageName);
|
||||
removeOverrideUnsafe(change.getId(), packageName);
|
||||
}
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
@@ -372,8 +402,10 @@ final class CompatConfig {
|
||||
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) {
|
||||
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
||||
for (long changeId : changes) {
|
||||
addOverride(changeId, packageName, true);
|
||||
addOverrideUnsafe(changeId, packageName, true);
|
||||
}
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
return changes.length;
|
||||
}
|
||||
|
||||
@@ -386,8 +418,10 @@ final class CompatConfig {
|
||||
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) {
|
||||
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
||||
for (long changeId : changes) {
|
||||
addOverride(changeId, packageName, false);
|
||||
addOverrideUnsafe(changeId, packageName, false);
|
||||
}
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
return changes.length;
|
||||
}
|
||||
|
||||
@@ -494,7 +528,8 @@ final class CompatConfig {
|
||||
|
||||
private void readConfig(File configFile) {
|
||||
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
|
||||
for (Change change : XmlParser.read(in).getCompatChange()) {
|
||||
Config config = com.android.server.compat.config.XmlParser.read(in);
|
||||
for (Change change : config.getCompatChange()) {
|
||||
Slog.d(TAG, "Adding: " + change.toString());
|
||||
addChange(new CompatChange(change));
|
||||
}
|
||||
@@ -503,6 +538,65 @@ final class CompatConfig {
|
||||
}
|
||||
}
|
||||
|
||||
void initOverrides(File overridesFile) {
|
||||
if (!overridesFile.exists()) {
|
||||
mOverridesFile = overridesFile;
|
||||
// There have not been any overrides added yet.
|
||||
return;
|
||||
}
|
||||
|
||||
try (InputStream in = new BufferedInputStream(new FileInputStream(overridesFile))) {
|
||||
Overrides overrides = com.android.server.compat.overrides.XmlParser.read(in);
|
||||
for (ChangeOverrides changeOverrides : overrides.getChangeOverrides()) {
|
||||
long changeId = changeOverrides.getChangeId();
|
||||
CompatChange compatChange = mChanges.get(changeId);
|
||||
if (compatChange == null) {
|
||||
Slog.w(TAG, "Change ID " + changeId + " not found. "
|
||||
+ "Skipping overrides for it.");
|
||||
continue;
|
||||
}
|
||||
compatChange.loadOverrides(changeOverrides);
|
||||
}
|
||||
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
|
||||
Slog.w(TAG, "Error processing " + overridesFile + " " + e.toString());
|
||||
return;
|
||||
}
|
||||
mOverridesFile = overridesFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist compat framework overrides to /data/misc/appcompat/compat_framework_overrides.xml
|
||||
*/
|
||||
void saveOverrides() {
|
||||
if (mOverridesFile == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (mChanges) {
|
||||
// Create the file if it doesn't already exist
|
||||
try {
|
||||
mOverridesFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Could not create override config file: " + e.toString());
|
||||
return;
|
||||
}
|
||||
try (PrintWriter out = new PrintWriter(mOverridesFile)) {
|
||||
XmlWriter writer = new XmlWriter(out);
|
||||
Overrides overrides = new Overrides();
|
||||
List<ChangeOverrides> changeOverridesList = overrides.getChangeOverrides();
|
||||
for (int idx = 0; idx < mChanges.size(); ++idx) {
|
||||
CompatChange c = mChanges.valueAt(idx);
|
||||
ChangeOverrides changeOverrides = c.saveOverrides();
|
||||
if (changeOverrides != null) {
|
||||
changeOverridesList.add(changeOverrides);
|
||||
}
|
||||
}
|
||||
XmlWriter.write(writer, overrides);
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IOverrideValidator getOverrideValidator() {
|
||||
return mOverrideValidator;
|
||||
}
|
||||
|
||||
@@ -8,11 +8,19 @@ xsd_config {
|
||||
|
||||
xsd_config {
|
||||
name: "platform-compat-config",
|
||||
srcs: ["platform-compat-config.xsd"],
|
||||
api_dir: "platform-compat-schema",
|
||||
srcs: ["platform-compat/config/platform-compat-config.xsd"],
|
||||
api_dir: "platform-compat/config/schema",
|
||||
package_name: "com.android.server.compat.config",
|
||||
}
|
||||
|
||||
xsd_config {
|
||||
name: "platform-compat-overrides",
|
||||
srcs: ["platform-compat/overrides/platform-compat-overrides.xsd"],
|
||||
api_dir: "platform-compat/overrides/schema",
|
||||
package_name: "com.android.server.compat.overrides",
|
||||
gen_writer: true,
|
||||
}
|
||||
|
||||
|
||||
xsd_config {
|
||||
name: "display-device-config",
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2019 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- This defines the format of the XML file used to store compat config overrides in
|
||||
~ /data/misc/appcompat/compat_framework_overrides.xml
|
||||
-->
|
||||
<xs:schema version="2.0" elementFormDefault="qualified"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
|
||||
<xs:complexType name="override-value">
|
||||
<xs:attribute type="xs:string" name="packageName" use="required" />
|
||||
<xs:attribute type="xs:boolean" name="enabled" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="change-overrides">
|
||||
<xs:attribute type="xs:long" name="changeId" use="required"/>
|
||||
<xs:element name="validated">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="override-value" type="override-value" maxOccurs="unbounded" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="deferred">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="override-value" type="override-value" maxOccurs="unbounded" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="overrides">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="change-overrides" type="change-overrides" maxOccurs="unbounded" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,51 @@
|
||||
// Signature format: 2.0
|
||||
package com.android.server.compat.overrides {
|
||||
|
||||
public class ChangeOverrides {
|
||||
ctor public ChangeOverrides();
|
||||
method public long getChangeId();
|
||||
method public com.android.server.compat.overrides.ChangeOverrides.Deferred getDeferred();
|
||||
method public com.android.server.compat.overrides.ChangeOverrides.Validated getValidated();
|
||||
method public void setChangeId(long);
|
||||
method public void setDeferred(com.android.server.compat.overrides.ChangeOverrides.Deferred);
|
||||
method public void setValidated(com.android.server.compat.overrides.ChangeOverrides.Validated);
|
||||
}
|
||||
|
||||
public static class ChangeOverrides.Deferred {
|
||||
ctor public ChangeOverrides.Deferred();
|
||||
method public java.util.List<com.android.server.compat.overrides.OverrideValue> getOverrideValue();
|
||||
}
|
||||
|
||||
public static class ChangeOverrides.Validated {
|
||||
ctor public ChangeOverrides.Validated();
|
||||
method public java.util.List<com.android.server.compat.overrides.OverrideValue> getOverrideValue();
|
||||
}
|
||||
|
||||
public class OverrideValue {
|
||||
ctor public OverrideValue();
|
||||
method public boolean getEnabled();
|
||||
method public String getPackageName();
|
||||
method public void setEnabled(boolean);
|
||||
method public void setPackageName(String);
|
||||
}
|
||||
|
||||
public class Overrides {
|
||||
ctor public Overrides();
|
||||
method public java.util.List<com.android.server.compat.overrides.ChangeOverrides> getChangeOverrides();
|
||||
}
|
||||
|
||||
public class XmlParser {
|
||||
ctor public XmlParser();
|
||||
method public static com.android.server.compat.overrides.Overrides read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
}
|
||||
|
||||
public class XmlWriter implements java.io.Closeable {
|
||||
ctor public XmlWriter(java.io.PrintWriter);
|
||||
method public void close();
|
||||
method public static void write(com.android.server.compat.overrides.XmlWriter, com.android.server.compat.overrides.Overrides) throws java.io.IOException;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
// Signature format: 2.0
|
||||
@@ -44,6 +44,8 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.UUID;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -69,6 +71,10 @@ public class CompatConfigTest {
|
||||
os.close();
|
||||
}
|
||||
|
||||
private String readFile(File file) throws IOException {
|
||||
return new String(Files.readAllBytes(Paths.get(file.toURI())));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -499,4 +505,86 @@ public class CompatConfigTest {
|
||||
assertThat(compatConfig.isChangeEnabled(1236L,
|
||||
ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveOverrides() throws Exception {
|
||||
File overridesFile = new File(createTempDir(), "overrides.xml");
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledChangeWithId(1L)
|
||||
.addEnableSinceSdkChangeWithId(2, 2L)
|
||||
.build();
|
||||
compatConfig.forceNonDebuggableFinalForTest(true);
|
||||
compatConfig.initOverrides(overridesFile);
|
||||
when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt()))
|
||||
.thenReturn(ApplicationInfoBuilder.create()
|
||||
.withPackageName("foo.bar")
|
||||
.debuggable()
|
||||
.build());
|
||||
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
|
||||
.thenThrow(new NameNotFoundException());
|
||||
|
||||
compatConfig.addOverride(1L, "foo.bar", true);
|
||||
compatConfig.addOverride(2L, "bar.baz", false);
|
||||
|
||||
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
+ "<overrides>\n"
|
||||
+ " <change-overrides changeId=\"1\">\n"
|
||||
+ " <validated>\n"
|
||||
+ " <override-value packageName=\"foo.bar\" enabled=\"true\">\n"
|
||||
+ " </override-value>\n"
|
||||
+ " </validated>\n"
|
||||
+ " <deferred>\n"
|
||||
+ " </deferred>\n"
|
||||
+ " </change-overrides>\n"
|
||||
+ " <change-overrides changeId=\"2\">\n"
|
||||
+ " <validated>\n"
|
||||
+ " </validated>\n"
|
||||
+ " <deferred>\n"
|
||||
+ " <override-value packageName=\"bar.baz\" enabled=\"false\">\n"
|
||||
+ " </override-value>\n"
|
||||
+ " </deferred>\n"
|
||||
+ " </change-overrides>\n"
|
||||
+ "</overrides>\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadOverrides() 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)
|
||||
String xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||
+ "<overrides>"
|
||||
+ "<change-overrides changeId=\"1\">"
|
||||
+ "<deferred/>"
|
||||
+ "<validated>"
|
||||
+ "<override-value packageName=\"foo.bar\" enabled=\"true\"/>"
|
||||
+ "</validated>"
|
||||
+ "</change-overrides>"
|
||||
+ "<change-overrides changeId=\"2\">"
|
||||
+ "<deferred>"
|
||||
+ "<override-value packageName=\"bar.baz\" enabled=\"false\"/>"
|
||||
+ "</deferred>"
|
||||
+ "<validated/>"
|
||||
+ "</change-overrides>"
|
||||
+ "</overrides>";
|
||||
writeToFile(tempDir, "overrides.xml", xmlData);
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledChangeWithId(1L)
|
||||
.addEnableSinceSdkChangeWithId(2, 2L)
|
||||
.build();
|
||||
compatConfig.forceNonDebuggableFinalForTest(true);
|
||||
compatConfig.initOverrides(overridesFile);
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("foo.bar")
|
||||
.debuggable()
|
||||
.build();
|
||||
when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
|
||||
.thenThrow(new NameNotFoundException());
|
||||
|
||||
assertThat(compatConfig.isChangeEnabled(1L, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user