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

Commit f9266a29 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Migrate SettingsProvider to support typed XML.

Mechanical refactoring to migrate to using typed XML, which paves
the way for a future pivot to a binary XML format.

Bug: 171832118
Test: atest SettingsProviderTest
Change-Id: I5c1b4ad2b5cd5d6e38c49ff1dfe25fcc35459349
parent 2d0c5b8a
Loading
Loading
Loading
Loading
+18 −24
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import android.util.Base64;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;

@@ -52,7 +54,6 @@ import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileInputStream;
@@ -60,7 +61,6 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -806,13 +806,10 @@ final class SettingsState {
            try {
                out = destination.startWrite();

                XmlSerializer serializer = Xml.newSerializer();
                serializer.setOutput(out, StandardCharsets.UTF_8.name());
                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
                        true);
                TypedXmlSerializer serializer = Xml.resolveSerializer(out);
                serializer.startDocument(null, true);
                serializer.startTag(null, TAG_SETTINGS);
                serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
                serializer.attributeInt(null, ATTR_VERSION, version);

                final int settingCount = settings.size();
                for (int i = 0; i < settingCount; i++) {
@@ -908,7 +905,7 @@ final class SettingsState {
        }
    }

    static void writeSingleSetting(int version, XmlSerializer serializer, String id,
    static void writeSingleSetting(int version, TypedXmlSerializer serializer, String id,
            String name, String value, String defaultValue, String packageName,
            String tag, boolean defaultSysSet, boolean isValuePreservedInRestore)
            throws IOException {
@@ -926,18 +923,18 @@ final class SettingsState {
        if (defaultValue != null) {
            setValueAttribute(ATTR_DEFAULT_VALUE, ATTR_DEFAULT_VALUE_BASE64,
                    version, serializer, defaultValue);
            serializer.attribute(null, ATTR_DEFAULT_SYS_SET, Boolean.toString(defaultSysSet));
            serializer.attributeBoolean(null, ATTR_DEFAULT_SYS_SET, defaultSysSet);
            setValueAttribute(ATTR_TAG, ATTR_TAG_BASE64,
                    version, serializer, tag);
        }
        if (isValuePreservedInRestore) {
            serializer.attribute(null, ATTR_PRESERVE_IN_RESTORE, Boolean.toString(true));
            serializer.attributeBoolean(null, ATTR_PRESERVE_IN_RESTORE, true);
        }
        serializer.endTag(null, TAG_SETTING);
    }

    static void setValueAttribute(String attr, String attrBase64, int version,
            XmlSerializer serializer, String value) throws IOException {
            TypedXmlSerializer serializer, String value) throws IOException {
        if (version >= SETTINGS_VERSION_NEW_ENCODING) {
            if (value == null) {
                // Null value -> No ATTR_VALUE nor ATTR_VALUE_BASE64.
@@ -956,7 +953,7 @@ final class SettingsState {
        }
    }

    private static void writeSingleNamespaceHash(XmlSerializer serializer, String namespace,
    private static void writeSingleNamespaceHash(TypedXmlSerializer serializer, String namespace,
            String bannedHashCode) throws IOException {
        if (namespace == null || bannedHashCode == null) {
            return;
@@ -971,7 +968,7 @@ final class SettingsState {
        return Integer.toString(keyValues.hashCode());
    }

    private String getValueAttribute(XmlPullParser parser, String attr, String base64Attr) {
    private String getValueAttribute(TypedXmlPullParser parser, String attr, String base64Attr) {
        if (mVersion >= SETTINGS_VERSION_NEW_ENCODING) {
            final String value = parser.getAttributeValue(null, attr);
            if (value != null) {
@@ -1039,8 +1036,7 @@ final class SettingsState {
    @GuardedBy("mLock")
    private boolean parseStateFromXmlStreamLocked(FileInputStream in) {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, StandardCharsets.UTF_8.name());
            TypedXmlPullParser parser = Xml.resolvePullParser(in);
            parseStateLocked(parser);
            return true;
        } catch (XmlPullParserException | IOException e) {
@@ -1060,7 +1056,7 @@ final class SettingsState {
        return stateFile.exists();
    }

    private void parseStateLocked(XmlPullParser parser)
    private void parseStateLocked(TypedXmlPullParser parser)
            throws IOException, XmlPullParserException {
        final int outerDepth = parser.getDepth();
        int type;
@@ -1080,10 +1076,10 @@ final class SettingsState {
    }

    @GuardedBy("mLock")
    private void parseSettingsLocked(XmlPullParser parser)
    private void parseSettingsLocked(TypedXmlPullParser parser)
            throws IOException, XmlPullParserException {

        mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION));
        mVersion = parser.getAttributeInt(null, ATTR_VERSION);

        final int outerDepth = parser.getDepth();
        int type;
@@ -1101,14 +1097,12 @@ final class SettingsState {
                String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                String defaultValue = getValueAttribute(parser, ATTR_DEFAULT_VALUE,
                        ATTR_DEFAULT_VALUE_BASE64);
                String isPreservedInRestoreString = parser.getAttributeValue(null,
                        ATTR_PRESERVE_IN_RESTORE);
                boolean isPreservedInRestore = Boolean.parseBoolean(isPreservedInRestoreString);
                boolean isPreservedInRestore = parser.getAttributeBoolean(null,
                        ATTR_PRESERVE_IN_RESTORE, false);
                String tag = null;
                boolean fromSystem = false;
                if (defaultValue != null) {
                    fromSystem = Boolean.parseBoolean(parser.getAttributeValue(
                            null, ATTR_DEFAULT_SYS_SET));
                    fromSystem = parser.getAttributeBoolean(null, ATTR_DEFAULT_SYS_SET, false);
                    tag = getValueAttribute(parser, ATTR_TAG, ATTR_TAG_BASE64);
                }
                mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
@@ -1122,7 +1116,7 @@ final class SettingsState {
    }

    @GuardedBy("mLock")
    private void parseNamespaceHash(XmlPullParser parser)
    private void parseNamespaceHash(TypedXmlPullParser parser)
            throws IOException, XmlPullParserException {

        final int outerDepth = parser.getDepth();
+4 −8
Original line number Diff line number Diff line
@@ -17,15 +17,13 @@ package com.android.providers.settings;

import android.os.Looper;
import android.test.AndroidTestCase;
import android.util.TypedXmlSerializer;
import android.util.Xml;

import org.xmlpull.v1.XmlSerializer;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;

public class SettingsStateTest extends AndroidTestCase {
    public static final String CRAZY_STRING =
@@ -93,9 +91,7 @@ public class SettingsStateTest extends AndroidTestCase {
    public void testWriteReadNoCrash() throws Exception {
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        XmlSerializer serializer = Xml.newSerializer();
        serializer.setOutput(os, StandardCharsets.UTF_8.name());
        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
        TypedXmlSerializer serializer = Xml.resolveSerializer(os);
        serializer.startDocument(null, true);

        for (int ch = 0; ch < 0x10000; ch++) {
@@ -118,12 +114,12 @@ public class SettingsStateTest extends AndroidTestCase {
                serializer, "1", "k", "v", null, null, null, false, false);
    }

    private void checkWriteSingleSetting(XmlSerializer serializer, String key, String value)
    private void checkWriteSingleSetting(TypedXmlSerializer serializer, String key, String value)
            throws Exception {
        checkWriteSingleSetting(key + "/" + value, serializer, key, value);
    }

    private void checkWriteSingleSetting(String msg, XmlSerializer serializer,
    private void checkWriteSingleSetting(String msg, TypedXmlSerializer serializer,
            String key, String value) throws Exception {
        // Make sure the XML serializer won't crash.
        SettingsState.writeSingleSetting(