Merge "Persists share targets after reading from Apps xml resource" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ffdf5b5639
@@ -15,12 +15,36 @@
|
||||
*/
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents a Share Target definition, read from the application's manifest (shortcuts.xml)
|
||||
*/
|
||||
class ShareTargetInfo {
|
||||
|
||||
private static final String TAG_SHARE_TARGET = "share-target";
|
||||
private static final String ATTR_TARGET_CLASS = "targetClass";
|
||||
|
||||
private static final String TAG_DATA = "data";
|
||||
private static final String ATTR_SCHEME = "scheme";
|
||||
private static final String ATTR_HOST = "host";
|
||||
private static final String ATTR_PORT = "port";
|
||||
private static final String ATTR_PATH = "path";
|
||||
private static final String ATTR_PATH_PATTERN = "pathPattern";
|
||||
private static final String ATTR_PATH_PREFIX = "pathPrefix";
|
||||
private static final String ATTR_MIME_TYPE = "mimeType";
|
||||
|
||||
private static final String TAG_CATEGORY = "category";
|
||||
private static final String ATTR_NAME = "name";
|
||||
|
||||
static class TargetData {
|
||||
final String mScheme;
|
||||
final String mHost;
|
||||
@@ -98,4 +122,72 @@ class ShareTargetInfo {
|
||||
|
||||
return strBuilder.toString();
|
||||
}
|
||||
|
||||
void saveToXml(@NonNull XmlSerializer out) throws IOException {
|
||||
out.startTag(null, TAG_SHARE_TARGET);
|
||||
|
||||
ShortcutService.writeAttr(out, ATTR_TARGET_CLASS, mTargetClass);
|
||||
|
||||
for (int i = 0; i < mTargetData.length; i++) {
|
||||
out.startTag(null, TAG_DATA);
|
||||
ShortcutService.writeAttr(out, ATTR_SCHEME, mTargetData[i].mScheme);
|
||||
ShortcutService.writeAttr(out, ATTR_HOST, mTargetData[i].mHost);
|
||||
ShortcutService.writeAttr(out, ATTR_PORT, mTargetData[i].mPort);
|
||||
ShortcutService.writeAttr(out, ATTR_PATH, mTargetData[i].mPath);
|
||||
ShortcutService.writeAttr(out, ATTR_PATH_PATTERN, mTargetData[i].mPathPattern);
|
||||
ShortcutService.writeAttr(out, ATTR_PATH_PREFIX, mTargetData[i].mPathPrefix);
|
||||
ShortcutService.writeAttr(out, ATTR_MIME_TYPE, mTargetData[i].mMimeType);
|
||||
out.endTag(null, TAG_DATA);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mCategories.length; i++) {
|
||||
out.startTag(null, TAG_CATEGORY);
|
||||
ShortcutService.writeAttr(out, ATTR_NAME, mCategories[i]);
|
||||
out.endTag(null, TAG_CATEGORY);
|
||||
}
|
||||
|
||||
out.endTag(null, TAG_SHARE_TARGET);
|
||||
}
|
||||
|
||||
static ShareTargetInfo loadFromXml(XmlPullParser parser)
|
||||
throws IOException, XmlPullParserException {
|
||||
final String targetClass = ShortcutService.parseStringAttribute(parser, ATTR_TARGET_CLASS);
|
||||
final ArrayList<ShareTargetInfo.TargetData> targetData = new ArrayList<>();
|
||||
final ArrayList<String> categories = new ArrayList<>();
|
||||
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
switch (parser.getName()) {
|
||||
case TAG_DATA:
|
||||
targetData.add(parseTargetData(parser));
|
||||
break;
|
||||
case TAG_CATEGORY:
|
||||
categories.add(ShortcutService.parseStringAttribute(parser, ATTR_NAME));
|
||||
break;
|
||||
}
|
||||
} else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_SHARE_TARGET)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetData.isEmpty() || targetClass == null || categories.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new ShareTargetInfo(
|
||||
targetData.toArray(new ShareTargetInfo.TargetData[targetData.size()]),
|
||||
targetClass, categories.toArray(new String[categories.size()]));
|
||||
}
|
||||
|
||||
private static ShareTargetInfo.TargetData parseTargetData(XmlPullParser parser) {
|
||||
final String scheme = ShortcutService.parseStringAttribute(parser, ATTR_SCHEME);
|
||||
final String host = ShortcutService.parseStringAttribute(parser, ATTR_HOST);
|
||||
final String port = ShortcutService.parseStringAttribute(parser, ATTR_PORT);
|
||||
final String path = ShortcutService.parseStringAttribute(parser, ATTR_PATH);
|
||||
final String pathPattern = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PATTERN);
|
||||
final String pathPrefix = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PREFIX);
|
||||
final String mimeType = ShortcutService.parseStringAttribute(parser, ATTR_MIME_TYPE);
|
||||
|
||||
return new ShareTargetInfo.TargetData(scheme, host, port, path, pathPattern, pathPrefix,
|
||||
mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
private static final String TAG_INTENT = "intent";
|
||||
private static final String TAG_EXTRAS = "extras";
|
||||
private static final String TAG_SHORTCUT = "shortcut";
|
||||
private static final String TAG_SHARE_TARGET = "share-target";
|
||||
private static final String TAG_CATEGORIES = "categories";
|
||||
private static final String TAG_PERSON = "person";
|
||||
|
||||
@@ -1453,8 +1454,9 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
public void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
|
||||
throws IOException, XmlPullParserException {
|
||||
final int size = mShortcuts.size();
|
||||
final int shareTargetSize = mShareTargets.size();
|
||||
|
||||
if (size == 0 && mApiCallCount == 0) {
|
||||
if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0) {
|
||||
return; // nothing to write.
|
||||
}
|
||||
|
||||
@@ -1470,6 +1472,12 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
getPackageInfo().isBackupAllowed());
|
||||
}
|
||||
|
||||
if (!forBackup) {
|
||||
for (int j = 0; j < shareTargetSize; j++) {
|
||||
mShareTargets.get(j).saveToXml(out);
|
||||
}
|
||||
}
|
||||
|
||||
out.endTag(null, TAG_ROOT);
|
||||
}
|
||||
|
||||
@@ -1627,6 +1635,9 @@ class ShortcutPackage extends ShortcutPackageItem {
|
||||
// Don't use addShortcut(), we don't need to save the icon.
|
||||
ret.mShortcuts.put(si.getId(), si);
|
||||
continue;
|
||||
case TAG_SHARE_TARGET:
|
||||
ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ShortcutService.warnForInvalidTag(depth, tag);
|
||||
|
||||
@@ -97,16 +97,25 @@ import android.os.UserHandle;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.frameworks.servicestests.R;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.server.pm.ShortcutService.ConfigConstants;
|
||||
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
|
||||
import com.android.server.pm.ShortcutUser.PackageWithUser;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -8089,4 +8098,70 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
|
||||
List<ShareTargetInfo> expectedValues = new ArrayList<>();
|
||||
expectedValues.add(new ShareTargetInfo(
|
||||
new ShareTargetInfo.TargetData[]{new ShareTargetInfo.TargetData(
|
||||
"http", "www.google.com", "1234", "somePath", "somePathPattern",
|
||||
"somePathPrefix", "text/plain")}, "com.test.directshare.TestActivity1",
|
||||
new String[]{"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"}));
|
||||
expectedValues.add(new ShareTargetInfo(new ShareTargetInfo.TargetData[]{
|
||||
new ShareTargetInfo.TargetData(null, null, null, null, null, null, "video/mp4"),
|
||||
new ShareTargetInfo.TargetData("content", null, null, null, null, null, "video/*")},
|
||||
"com.test.directshare.TestActivity5",
|
||||
new String[]{"com.test.category.CATEGORY5", "com.test.category.CATEGORY6"}));
|
||||
|
||||
// Write ShareTargets to Xml
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
final XmlSerializer outXml = new FastXmlSerializer();
|
||||
outXml.setOutput(outStream, StandardCharsets.UTF_8.name());
|
||||
outXml.startDocument(null, true);
|
||||
for (int i = 0; i < expectedValues.size(); i++) {
|
||||
expectedValues.get(i).saveToXml(outXml);
|
||||
}
|
||||
outXml.endDocument();
|
||||
outXml.flush();
|
||||
|
||||
// Read ShareTargets from Xml
|
||||
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setInput(new InputStreamReader(inStream));
|
||||
List<ShareTargetInfo> shareTargets = new ArrayList<>();
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
if (type == XmlPullParser.START_TAG && parser.getName().equals("share-target")) {
|
||||
shareTargets.add(ShareTargetInfo.loadFromXml(parser));
|
||||
}
|
||||
}
|
||||
|
||||
// Assert two lists are equal
|
||||
assertNotNull(shareTargets);
|
||||
assertEquals(expectedValues.size(), shareTargets.size());
|
||||
|
||||
for (int i = 0; i < expectedValues.size(); i++) {
|
||||
ShareTargetInfo expected = expectedValues.get(i);
|
||||
ShareTargetInfo actual = shareTargets.get(i);
|
||||
|
||||
assertEquals(expected.mTargetData.length, actual.mTargetData.length);
|
||||
for (int j = 0; j < expected.mTargetData.length; j++) {
|
||||
assertEquals(expected.mTargetData[j].mScheme, actual.mTargetData[j].mScheme);
|
||||
assertEquals(expected.mTargetData[j].mHost, actual.mTargetData[j].mHost);
|
||||
assertEquals(expected.mTargetData[j].mPort, actual.mTargetData[j].mPort);
|
||||
assertEquals(expected.mTargetData[j].mPath, actual.mTargetData[j].mPath);
|
||||
assertEquals(expected.mTargetData[j].mPathPrefix,
|
||||
actual.mTargetData[j].mPathPrefix);
|
||||
assertEquals(expected.mTargetData[j].mPathPattern,
|
||||
actual.mTargetData[j].mPathPattern);
|
||||
assertEquals(expected.mTargetData[j].mMimeType, actual.mTargetData[j].mMimeType);
|
||||
}
|
||||
|
||||
assertEquals(expected.mTargetClass, actual.mTargetClass);
|
||||
|
||||
assertEquals(expected.mCategories.length, actual.mCategories.length);
|
||||
for (int j = 0; j < expected.mCategories.length; j++) {
|
||||
assertEquals(expected.mCategories[j], actual.mCategories[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user