Read compat config in CompatConfig class.

Use the auto generated parser, and test by feeding streams of XML.

Test: atest FrameworksServicesTests
Bug: 138222871
Change-Id: Id523d31e7b6d2def9371753ae34cba883cd62a54
This commit is contained in:
atrost
2019-07-24 14:12:48 +01:00
parent b7d3ffef37
commit bc0f406751
5 changed files with 129 additions and 2 deletions

View File

@@ -20,6 +20,7 @@ java_library_static {
":storaged_aidl", ":storaged_aidl",
":vold_aidl", ":vold_aidl",
":gsiservice_aidl", ":gsiservice_aidl",
":platform-compat-config",
"java/com/android/server/EventLogTags.logtags", "java/com/android/server/EventLogTags.logtags",
"java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags",
"java/com/android/server/policy/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags",

View File

@@ -20,6 +20,8 @@ import android.annotation.Nullable;
import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledAfter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import com.android.server.compat.config.Change;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -60,6 +62,16 @@ public final class CompatChange {
mDisabled = disabled; mDisabled = disabled;
} }
/**
* @param change an object generated by services/core/xsd/platform-compat-config.xsd
*/
public CompatChange(Change change) {
mChangeId = change.getId();
mName = change.getName();
mEnableAfterTargetSdk = change.getEnableAfterTargetSdk();
mDisabled = change.getDisabled();
}
long getId() { long getId() {
return mChangeId; return mChangeId;
} }

View File

@@ -17,14 +17,27 @@
package com.android.server.compat; package com.android.server.compat;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.os.Environment;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.LongArray; import android.util.LongArray;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.compat.config.Change;
import com.android.server.compat.config.XmlParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import javax.xml.datatype.DatatypeConfigurationException;
/** /**
* This class maintains state relating to platform compatibility changes. * This class maintains state relating to platform compatibility changes.
* *
@@ -33,7 +46,12 @@ import java.io.PrintWriter;
*/ */
public final class CompatConfig { public final class CompatConfig {
private static final CompatConfig sInstance = new CompatConfig(); private static final String TAG = "CompatConfig";
private static final String CONFIG_FILE_SUFFIX = "platform_compat_config.xml";
private static final CompatConfig sInstance = new CompatConfig().initConfigFromLib(
Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"));
@GuardedBy("mChanges") @GuardedBy("mChanges")
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
@@ -188,4 +206,29 @@ public final class CompatConfig {
} }
} }
CompatConfig initConfigFromLib(File libraryDir) {
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Slog.e(TAG, "No directory " + libraryDir + ", skipping");
return this;
}
for (File f : libraryDir.listFiles()) {
//TODO(b/138222363): Handle duplicate ids across config files.
if (f.getPath().endsWith(CONFIG_FILE_SUFFIX)) {
readConfig(f);
}
}
return this;
}
private void readConfig(File configFile) {
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
for (Change change : XmlParser.read(in).getCompatChange()) {
Slog.w(TAG, "Adding: " + change.toString());
addChange(new CompatChange(change));
}
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
Slog.e(TAG, "Encountered an error while reading/parsing compat config file", e);
}
}
} }

View File

@@ -39,6 +39,7 @@ android_test {
"platformprotosnano", "platformprotosnano",
"hamcrest-library", "hamcrest-library",
"servicestests-utils", "servicestests-utils",
"xml-writer-device-lib",
], ],
aidl: { aidl: {

View File

@@ -22,9 +22,17 @@ import android.content.pm.ApplicationInfo;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.compat.annotation.Change;
import com.android.compat.annotation.XmlWriter;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class CompatConfigTest { public class CompatConfigTest {
@@ -35,6 +43,27 @@ public class CompatConfigTest {
return ai; return ai;
} }
private File createTempDir() {
String base = System.getProperty("java.io.tmpdir");
File dir = new File(base, UUID.randomUUID().toString());
assertThat(dir.mkdirs()).isTrue();
return dir;
}
private void writeChangesToFile(Change[] changes, File f) {
XmlWriter writer = new XmlWriter();
for (Change change: changes) {
writer.addChange(change);
}
try {
f.createNewFile();
writer.write(new FileOutputStream(f));
} catch (IOException e) {
throw new RuntimeException(
"Encountered an error while writing compat config file", e);
}
}
@Test @Test
public void testUnknownChangeEnabled() { public void testUnknownChangeEnabled() {
CompatConfig pc = new CompatConfig(); CompatConfig pc = new CompatConfig();
@@ -170,4 +199,45 @@ public class CompatConfigTest {
sysApp.flags |= ApplicationInfo.FLAG_SYSTEM; sysApp.flags |= ApplicationInfo.FLAG_SYSTEM;
assertThat(pc.isChangeEnabled(1234L, sysApp)).isTrue(); assertThat(pc.isChangeEnabled(1234L, sysApp)).isTrue();
} }
@Test
public void testReadConfig() {
Change[] changes = {new Change(1234L, "MY_CHANGE1", false, 2), new Change(1235L,
"MY_CHANGE2", true, null), new Change(1236L, "MY_CHANGE3", false, null)};
File dir = createTempDir();
writeChangesToFile(changes, new File(dir.getPath() + "/platform_compat_config.xml"));
CompatConfig pc = new CompatConfig();
pc.initConfigFromLib(dir);
assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse();
assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue();
}
@Test
public void testReadConfigMultipleFiles() {
Change[] changes1 = {new Change(1234L, "MY_CHANGE1", false, 2)};
Change[] changes2 = {new Change(1235L, "MY_CHANGE2", true, null), new Change(1236L,
"MY_CHANGE3", false, null)};
File dir = createTempDir();
writeChangesToFile(changes1,
new File(dir.getPath() + "/libcore_platform_compat_config.xml"));
writeChangesToFile(changes2,
new File(dir.getPath() + "/frameworks_platform_compat_config.xml"));
CompatConfig pc = new CompatConfig();
pc.initConfigFromLib(dir);
assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse();
assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue();
}
} }