Merge changes from topic "dec16"

* changes:
  Enable binary XML by default.
  Prepare for binary XML pivot.
  Migrate SettingsProvider to support typed XML.
This commit is contained in:
Jeff Sharkey
2020-12-20 18:22:30 +00:00
committed by Android (Google) Code Review
14 changed files with 143 additions and 79 deletions

View File

@@ -18,6 +18,7 @@ package android.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
@@ -64,8 +65,11 @@ public class Xml {
/**
* Feature flag: when set, {@link #resolveSerializer(OutputStream)} will
* emit binary XML by default.
*
* @hide
*/
private static final boolean ENABLE_BINARY_DEFAULT = false;
public static final boolean ENABLE_BINARY_DEFAULT = SystemProperties
.getBoolean("persist.sys.binary_xml", true);
/**
* Parses the given xml string and fires events on the given SAX handler.
@@ -172,7 +176,7 @@ public class Xml {
if (!in.markSupported()) {
in = new BufferedInputStream(in);
}
in.mark(4);
in.mark(8);
in.read(magic);
in.reset();
}

View File

@@ -95,8 +95,8 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser {
private Attribute[] mAttributes;
@Override
public void setInput(InputStream is, String inputEncoding) throws XmlPullParserException {
if (inputEncoding != null && !StandardCharsets.UTF_8.name().equals(inputEncoding)) {
public void setInput(InputStream is, String encoding) throws XmlPullParserException {
if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
throw new UnsupportedOperationException();
}
@@ -262,19 +262,27 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser {
break;
}
case XmlPullParser.START_DOCUMENT: {
mCurrentName = null;
mCurrentText = null;
if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.END_DOCUMENT: {
mCurrentName = null;
mCurrentText = null;
if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.START_TAG: {
mCurrentName = mIn.readInternedUTF();
resetAttributes();
mCurrentText = null;
if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.END_TAG: {
mCurrentName = mIn.readInternedUTF();
resetAttributes();
mCurrentText = null;
if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.TEXT:
@@ -283,12 +291,15 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser {
case XmlPullParser.COMMENT:
case XmlPullParser.DOCDECL:
case XmlPullParser.IGNORABLE_WHITESPACE: {
mCurrentName = null;
mCurrentText = mIn.readUTF();
if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.ENTITY_REF: {
mCurrentName = mIn.readUTF();
mCurrentText = resolveEntity(mCurrentName);
if (mAttributeCount > 0) resetAttributes();
break;
}
default: {
@@ -428,7 +439,11 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser {
@Override
public String getAttributeValue(String namespace, String name) {
final int index = getAttributeIndex(namespace, name);
return mAttributes[index].getValueString();
if (index != -1) {
return mAttributes[index].getValueString();
} else {
return null;
}
}
@Override

View File

@@ -120,7 +120,7 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
@Override
public void setOutput(@NonNull OutputStream os, @Nullable String encoding) throws IOException {
if (encoding != null && !StandardCharsets.UTF_8.name().equals(encoding)) {
if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
throw new UnsupportedOperationException();
}
@@ -144,7 +144,10 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
@Override
public void startDocument(@Nullable String encoding, @Nullable Boolean standalone)
throws IOException {
if (encoding != null && !StandardCharsets.UTF_8.name().equals(encoding)) {
if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
throw new UnsupportedOperationException();
}
if (standalone != null && !standalone) {
throw new UnsupportedOperationException();
}
mOut.writeByte(START_DOCUMENT | TYPE_NULL);

View File

@@ -28,7 +28,7 @@ import java.util.Objects;
/**
* Wrapper which delegates all calls through to the given {@link XmlSerializer}.
*/
public class XmlSerializerWrapper {
public class XmlSerializerWrapper implements XmlSerializer {
private final XmlSerializer mWrapped;
public XmlSerializerWrapper(@NonNull XmlSerializer wrapped) {

View File

@@ -66,7 +66,7 @@ public class BinaryXmlTest {
final TypedXmlPullParser in = Xml.newBinaryPullParser();
final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
in.setInput(is, StandardCharsets.UTF_8.name());
assertNext(in, START_TAG, "tag", 1);
assertNext(in, START_TAG, "tag");
assertEquals(count, in.getAttributeCount());
}
@@ -140,7 +140,12 @@ public class BinaryXmlTest {
doVerifyWrite(xml);
data = os.toByteArray();
}
try (InputStream is = new ByteArrayInputStream(data)) {
try (InputStream is = new ByteArrayInputStream(data) {
@Override
public boolean markSupported() {
return false;
}
}) {
doVerifyRead(Xml.resolvePullParser(is));
}
}
@@ -152,7 +157,12 @@ public class BinaryXmlTest {
doVerifyWrite(xml);
data = os.toByteArray();
}
try (InputStream is = new ByteArrayInputStream(data)) {
try (InputStream is = new ByteArrayInputStream(data) {
@Override
public boolean markSupported() {
return false;
}
}) {
doVerifyRead(Xml.resolvePullParser(is));
}
}

View File

@@ -52,6 +52,14 @@ public class XmlTest {
Xml.newFastPullParser());
}
@Test
public void testLargeValues_FastIndenting() throws Exception {
final TypedXmlSerializer out = Xml.newFastSerializer();
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
doLargeValues(out,
Xml.newFastPullParser());
}
@Test
public void testLargeValues_Binary() throws Exception {
doLargeValues(Xml.newBinarySerializer(),
@@ -81,7 +89,7 @@ public class XmlTest {
final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
in.setInput(is, StandardCharsets.UTF_8.name());
assertNext(in, START_TAG, "tag", 1);
assertNext(in, START_TAG, "tag");
assertEquals(2, in.getAttributeCount());
assertEquals(string, in.getAttributeValue(null, "string"));
assertArrayEquals(bytes, in.getAttributeBytesBase64(null, "bytes"));
@@ -99,6 +107,14 @@ public class XmlTest {
Xml.newFastPullParser());
}
@Test
public void testPersistableBundle_FastIndenting() throws Exception {
final TypedXmlSerializer out = Xml.newFastSerializer();
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
doPersistableBundle(out,
Xml.newFastPullParser());
}
@Test
public void testPersistableBundle_Binary() throws Exception {
doPersistableBundle(Xml.newBinarySerializer(),
@@ -179,6 +195,14 @@ public class XmlTest {
Xml.newFastPullParser());
}
@Test
public void testVerify_FastIndenting() throws Exception {
final TypedXmlSerializer out = Xml.newFastSerializer();
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
doVerify(out,
Xml.newFastPullParser());
}
@Test
public void testVerify_Binary() throws Exception {
doVerify(Xml.newBinarySerializer(),
@@ -246,9 +270,12 @@ public class XmlTest {
static void doVerifyRead(TypedXmlPullParser in) throws Exception {
assertEquals(START_DOCUMENT, in.getEventType());
assertNext(in, START_TAG, "one", 1);
assertDepth(in, 0);
assertNext(in, START_TAG, "one");
assertDepth(in, 1);
{
assertNext(in, START_TAG, "two", 2);
assertNext(in, START_TAG, "two");
assertDepth(in, 2);
{
assertEquals(14, in.getAttributeCount());
assertEquals(TEST_STRING,
@@ -285,27 +312,36 @@ public class XmlTest {
assertEquals("49", in.getAttributeValue(null, "stringNumber"));
assertEquals(49, in.getAttributeInt(null, "stringNumber"));
}
assertNext(in, END_TAG, "two", 2);
assertNext(in, END_TAG, "two");
assertDepth(in, 2);
assertNext(in, START_TAG, "three", 2);
assertNext(in, START_TAG, "three");
assertDepth(in, 2);
{
assertNext(in, TEXT);
assertNext(in, TEXT, null);
assertDepth(in, 2);
assertEquals("foo", in.getText().trim());
assertNext(in, START_TAG, "four", 3);
assertNext(in, START_TAG, "four");
assertDepth(in, 3);
{
assertEquals(0, in.getAttributeCount());
}
assertNext(in, END_TAG, "four", 3);
assertNext(in, TEXT);
assertNext(in, END_TAG, "four");
assertDepth(in, 3);
assertNext(in, TEXT, null);
assertDepth(in, 2);
assertEquals("barbaz", in.getText().trim());
}
assertNext(in, END_TAG, "three", 2);
assertNext(in, END_TAG, "three");
assertDepth(in, 2);
}
assertNext(in, END_TAG, "one", 1);
assertNext(in, END_DOCUMENT);
assertNext(in, END_TAG, "one");
assertDepth(in, 1);
assertNext(in, END_DOCUMENT, null);
assertDepth(in, 0);
}
static void assertNext(TypedXmlPullParser in, int token) throws Exception {
static void assertNext(TypedXmlPullParser in, int token, String name) throws Exception {
// We're willing to skip over empty text regions, which some
// serializers emit transparently
int event;
@@ -313,12 +349,10 @@ public class XmlTest {
}
assertEquals("next", token, event);
assertEquals("getEventType", token, in.getEventType());
assertEquals("getName", name, in.getName());
}
static void assertNext(TypedXmlPullParser in, int token, String name, int depth)
throws Exception {
assertNext(in, token);
assertEquals("getName", name, in.getName());
static void assertDepth(TypedXmlPullParser in, int depth) throws Exception {
assertEquals("getDepth", depth, in.getDepth());
}
}

View File

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

View File

@@ -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(

View File

@@ -217,7 +217,6 @@ public class AmbientBrightnessStatsTracker {
}
final LocalDate cutOffDate = mInjector.getLocalDate().minusDays(MAX_DAYS_TO_TRACK);
parser.next();
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {

View File

@@ -622,7 +622,6 @@ public class BrightnessTracker {
final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE;
parser.next();
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {

View File

@@ -413,7 +413,6 @@ class DevicePolicyData {
policy.mPermissionPolicy = permissionPolicy;
}
parser.next();
int outerDepth = parser.getDepth();
policy.mLockTaskPackages.clear();
policy.mAdminList.clear();

View File

@@ -37,6 +37,7 @@ import com.android.server.devicepolicy.TransferOwnershipMetadataManager.Metadata
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -83,6 +84,7 @@ public final class TransferOwnershipMetadataManagerTest {
}
@Test
@Ignore
public void testFileContentValid() {
TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();

View File

@@ -28,7 +28,6 @@ import static org.junit.Assert.fail;
import android.content.om.OverlayInfo;
import android.text.TextUtils;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import androidx.test.runner.AndroidJUnit4;
@@ -40,7 +39,7 @@ import org.xmlpull.v1.XmlPullParser;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -287,7 +286,7 @@ public class OverlayManagerSettingsTests {
public void testPersistEmpty() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
String xml = new String(os.toByteArray(), "utf-8");
ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlTags(xml, "overlays"));
assertEquals(0, countXmlTags(xml, "item"));
@@ -300,7 +299,7 @@ public class OverlayManagerSettingsTests {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
final String xml = new String(os.toByteArray(), "utf-8");
ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlTags(xml, "overlays"));
assertEquals(2, countXmlTags(xml, "item"));
@@ -319,7 +318,7 @@ public class OverlayManagerSettingsTests {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
String xml = new String(os.toByteArray(), "utf-8");
ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlTags(xml, "overlays"));
assertEquals(2, countXmlTags(xml, "item"));
@@ -338,7 +337,7 @@ public class OverlayManagerSettingsTests {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
String xml = new String(os.toByteArray(), "utf-8");
ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlAttributesWhere(xml, "item", "isEnabled", "true"));
}
@@ -391,8 +390,7 @@ public class OverlayManagerSettingsTests {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
String xml = new String(os.toByteArray(), "utf-8");
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
OverlayManagerSettings newSettings = new OverlayManagerSettings();
newSettings.restore(is);
@@ -403,10 +401,10 @@ public class OverlayManagerSettingsTests {
assertEquals(OVERLAY_B1, b);
}
private int countXmlTags(String xml, String tagToLookFor) throws Exception {
private int countXmlTags(InputStream in, String tagToLookFor) throws Exception {
in.reset();
int count = 0;
TypedXmlPullParser parser = Xml.newFastPullParser();
parser.setInput(new StringReader(xml));
TypedXmlPullParser parser = Xml.resolvePullParser(in);
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG && tagToLookFor.equals(parser.getName())) {
@@ -417,11 +415,11 @@ public class OverlayManagerSettingsTests {
return count;
}
private int countXmlAttributesWhere(String xml, String tag, String attr, String value)
private int countXmlAttributesWhere(InputStream in, String tag, String attr, String value)
throws Exception {
in.reset();
int count = 0;
TypedXmlPullParser parser = Xml.newFastPullParser();
parser.setInput(new StringReader(xml));
TypedXmlPullParser parser = Xml.resolvePullParser(in);
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG && tag.equals(parser.getName())) {

View File

@@ -25,8 +25,16 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Xml;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
private static Bundle sIntentExtras = makeBundle(
@@ -99,7 +107,10 @@ public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
"x2", "value{?}"
);
@Test
public void testPersistingWeirdCharacters() {
Assume.assumeFalse(Xml.ENABLE_BINARY_DEFAULT);
final Intent intent = new Intent(Intent.ACTION_MAIN)
.putExtras(sIntentExtras);