Loading services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ java_library_static { ":vold_aidl", ":gsiservice_aidl", ":mediaupdateservice_aidl", ":platform-compat-config", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", Loading services/core/java/com/android/server/compat/CompatChange.java +12 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.annotation.Nullable; import android.compat.annotation.EnabledAfter; import android.content.pm.ApplicationInfo; import com.android.server.compat.config.Change; import java.util.HashMap; import java.util.Map; Loading Loading @@ -60,6 +62,16 @@ public final class CompatChange { 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() { return mChangeId; } Loading services/core/java/com/android/server/compat/CompatConfig.java +44 −1 Original line number Diff line number Diff line Loading @@ -17,14 +17,27 @@ package com.android.server.compat; import android.content.pm.ApplicationInfo; import android.os.Environment; import android.text.TextUtils; import android.util.LongArray; import android.util.LongSparseArray; import android.util.Slog; import com.android.internal.annotations.GuardedBy; 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 javax.xml.datatype.DatatypeConfigurationException; /** * This class maintains state relating to platform compatibility changes. * Loading @@ -33,7 +46,12 @@ import java.io.PrintWriter; */ 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") private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); Loading Loading @@ -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); } } } services/tests/servicestests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ android_test { "ub-uiautomator", "platformprotosnano", "servicestests-utils", "xml-writer-device-lib", ], aidl: { Loading services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +70 −0 Original line number Diff line number Diff line Loading @@ -22,9 +22,17 @@ import android.content.pm.ApplicationInfo; import androidx.test.runner.AndroidJUnit4; import com.android.compat.annotation.Change; import com.android.compat.annotation.XmlWriter; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.UUID; @RunWith(AndroidJUnit4.class) public class CompatConfigTest { Loading @@ -35,6 +43,27 @@ public class CompatConfigTest { 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 public void testUnknownChangeEnabled() { CompatConfig pc = new CompatConfig(); Loading Loading @@ -170,4 +199,45 @@ public class CompatConfigTest { sysApp.flags |= ApplicationInfo.FLAG_SYSTEM; 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(); } } Loading
services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ java_library_static { ":vold_aidl", ":gsiservice_aidl", ":mediaupdateservice_aidl", ":platform-compat-config", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", Loading
services/core/java/com/android/server/compat/CompatChange.java +12 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.annotation.Nullable; import android.compat.annotation.EnabledAfter; import android.content.pm.ApplicationInfo; import com.android.server.compat.config.Change; import java.util.HashMap; import java.util.Map; Loading Loading @@ -60,6 +62,16 @@ public final class CompatChange { 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() { return mChangeId; } Loading
services/core/java/com/android/server/compat/CompatConfig.java +44 −1 Original line number Diff line number Diff line Loading @@ -17,14 +17,27 @@ package com.android.server.compat; import android.content.pm.ApplicationInfo; import android.os.Environment; import android.text.TextUtils; import android.util.LongArray; import android.util.LongSparseArray; import android.util.Slog; import com.android.internal.annotations.GuardedBy; 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 javax.xml.datatype.DatatypeConfigurationException; /** * This class maintains state relating to platform compatibility changes. * Loading @@ -33,7 +46,12 @@ import java.io.PrintWriter; */ 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") private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); Loading Loading @@ -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); } } }
services/tests/servicestests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ android_test { "ub-uiautomator", "platformprotosnano", "servicestests-utils", "xml-writer-device-lib", ], aidl: { Loading
services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +70 −0 Original line number Diff line number Diff line Loading @@ -22,9 +22,17 @@ import android.content.pm.ApplicationInfo; import androidx.test.runner.AndroidJUnit4; import com.android.compat.annotation.Change; import com.android.compat.annotation.XmlWriter; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.UUID; @RunWith(AndroidJUnit4.class) public class CompatConfigTest { Loading @@ -35,6 +43,27 @@ public class CompatConfigTest { 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 public void testUnknownChangeEnabled() { CompatConfig pc = new CompatConfig(); Loading Loading @@ -170,4 +199,45 @@ public class CompatConfigTest { sysApp.flags |= ApplicationInfo.FLAG_SYSTEM; 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(); } }