Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc0f4067 authored by atrost's avatar atrost
Browse files

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
parent b7d3ffef
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ java_library_static {
        ":storaged_aidl",
        ":vold_aidl",
        ":gsiservice_aidl",
        ":platform-compat-config",
        "java/com/android/server/EventLogTags.logtags",
        "java/com/android/server/am/EventLogTags.logtags",
        "java/com/android/server/policy/EventLogTags.logtags",
+12 −0
Original line number Diff line number Diff line
@@ -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;

@@ -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;
    }
+44 −1
Original line number Diff line number Diff line
@@ -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.
 *
@@ -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<>();
@@ -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);
        }
    }

}
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ android_test {
        "platformprotosnano",
        "hamcrest-library",
        "servicestests-utils",
        "xml-writer-device-lib",
    ],

    aidl: {
+70 −0
Original line number Diff line number Diff line
@@ -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 {

@@ -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();
@@ -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();
    }
}