summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2014-04-23 11:45:37 -0700
committerCraig Mautner <cmautner@google.com>2014-05-23 18:42:33 -0700
commit21d24a21ea4aaadd78e73de54168e8a8a8973e4d (patch)
treea06ea1745dfedcf8b118cee132c02a8b60cec6d1 /core
parentcd3a8245489fa36c528b075efe99a147cf4f6785 (diff)
downloadframeworks_base-21d24a21ea4aaadd78e73de54168e8a8a8973e4d.zip
frameworks_base-21d24a21ea4aaadd78e73de54168e8a8a8973e4d.tar.gz
frameworks_base-21d24a21ea4aaadd78e73de54168e8a8a8973e4d.tar.bz2
Add code for persisting tasks and activities to disk DO NOT MERGE
Recent tasks that have the persistable flag set are saved to /data/system/recent_tasks/ on shutdown and in the background. Their thumbnails are saved to /data/system/recent_images/. Change-Id: Ifb820a01c412fe1f8c0f6e41aa655fafd89eaa8d
Diffstat (limited to 'core')
-rw-r--r--core/java/android/content/Intent.java86
-rw-r--r--core/java/android/os/CommonBundle.java13
-rw-r--r--core/java/android/os/PersistableBundle.java97
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java550
4 files changed, 710 insertions, 36 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 076f657..f1391aa 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -45,6 +45,7 @@ import android.util.AttributeSet;
import android.util.Log;
import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.Serializable;
@@ -604,6 +605,15 @@ import java.util.Set;
* of all possible flags.
*/
public class Intent implements Parcelable, Cloneable {
+ private static final String ATTR_ACTION = "action";
+ private static final String TAG_CATEGORIES = "categories";
+ private static final String ATTR_CATEGORY = "category";
+ private static final String TAG_EXTRA = "extra";
+ private static final String ATTR_TYPE = "type";
+ private static final String ATTR_COMPONENT = "component";
+ private static final String ATTR_DATA = "data";
+ private static final String ATTR_FLAGS = "flags";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent activity actions (see action variable).
@@ -7347,7 +7357,7 @@ public class Intent implements Parcelable, Cloneable {
}
String nodeName = parser.getName();
- if (nodeName.equals("category")) {
+ if (nodeName.equals(TAG_CATEGORIES)) {
sa = resources.obtainAttributes(attrs,
com.android.internal.R.styleable.IntentCategory);
String cat = sa.getString(com.android.internal.R.styleable.IntentCategory_name);
@@ -7358,11 +7368,11 @@ public class Intent implements Parcelable, Cloneable {
}
XmlUtils.skipCurrentTag(parser);
- } else if (nodeName.equals("extra")) {
+ } else if (nodeName.equals(TAG_EXTRA)) {
if (intent.mExtras == null) {
intent.mExtras = new Bundle();
}
- resources.parseBundleExtra("extra", attrs, intent.mExtras);
+ resources.parseBundleExtra(TAG_EXTRA, attrs, intent.mExtras);
XmlUtils.skipCurrentTag(parser);
} else {
@@ -7373,6 +7383,76 @@ public class Intent implements Parcelable, Cloneable {
return intent;
}
+ /** @hide */
+ public void saveToXml(XmlSerializer out) throws IOException {
+ if (mAction != null) {
+ out.attribute(null, ATTR_ACTION, mAction);
+ }
+ if (mData != null) {
+ out.attribute(null, ATTR_DATA, mData.toString());
+ }
+ if (mType != null) {
+ out.attribute(null, ATTR_TYPE, mType);
+ }
+ if (mComponent != null) {
+ out.attribute(null, ATTR_COMPONENT, mComponent.flattenToShortString());
+ }
+ out.attribute(null, ATTR_FLAGS, Integer.toHexString(getFlags()));
+
+ if (mCategories != null) {
+ out.startTag(null, TAG_CATEGORIES);
+ for (int categoryNdx = mCategories.size() - 1; categoryNdx >= 0; --categoryNdx) {
+ out.attribute(null, ATTR_CATEGORY, mCategories.valueAt(categoryNdx));
+ }
+ }
+ }
+
+ /** @hide */
+ public static Intent restoreFromXml(XmlPullParser in) throws IOException,
+ XmlPullParserException {
+ Intent intent = new Intent();
+ final int outerDepth = in.getDepth();
+
+ int attrCount = in.getAttributeCount();
+ for (int attrNdx = attrCount - 1; attrNdx >= 0; --attrNdx) {
+ final String attrName = in.getAttributeName(attrNdx);
+ final String attrValue = in.getAttributeValue(attrNdx);
+ if (ATTR_ACTION.equals(attrName)) {
+ intent.setAction(attrValue);
+ } else if (ATTR_DATA.equals(attrName)) {
+ intent.setData(Uri.parse(attrValue));
+ } else if (ATTR_TYPE.equals(attrName)) {
+ intent.setType(attrValue);
+ } else if (ATTR_COMPONENT.equals(attrName)) {
+ intent.setComponent(ComponentName.unflattenFromString(attrValue));
+ } else if (ATTR_FLAGS.equals(attrName)) {
+ intent.setFlags(Integer.valueOf(attrValue, 16));
+ } else {
+ Log.e("Intent", "restoreFromXml: unknown attribute=" + attrName);
+ }
+ }
+
+ int event;
+ String name;
+ while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
+ (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+ if (event == XmlPullParser.START_TAG) {
+ name = in.getName();
+ if (TAG_CATEGORIES.equals(name)) {
+ attrCount = in.getAttributeCount();
+ for (int attrNdx = attrCount - 1; attrNdx >= 0; --attrNdx) {
+ intent.addCategory(in.getAttributeValue(attrNdx));
+ }
+ } else {
+ Log.w("Intent", "restoreFromXml: unknown name=" + name);
+ XmlUtils.skipCurrentTag(in);
+ }
+ }
+ }
+
+ return intent;
+ }
+
/**
* Normalize a MIME data type.
*
diff --git a/core/java/android/os/CommonBundle.java b/core/java/android/os/CommonBundle.java
index e11f170..c1b202c 100644
--- a/core/java/android/os/CommonBundle.java
+++ b/core/java/android/os/CommonBundle.java
@@ -18,11 +18,10 @@ package android.os;
import android.util.ArrayMap;
import android.util.Log;
-import android.util.SparseArray;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -304,6 +303,16 @@ abstract class CommonBundle implements Parcelable, Cloneable {
}
/**
+ * Inserts all mappings from the given Map into this CommonBundle.
+ *
+ * @param map a Map
+ */
+ void putAll(Map map) {
+ unparcel();
+ mMap.putAll(map);
+ }
+
+ /**
* Returns a Set containing the Strings used as keys in this Bundle.
*
* @return a Set of String keys
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index c2cd3be..cd8d515 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -17,7 +17,14 @@
package android.os;
import android.util.ArrayMap;
-
+import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
/**
@@ -25,7 +32,8 @@ import java.util.Set;
* restored.
*
*/
-public final class PersistableBundle extends CommonBundle {
+public final class PersistableBundle extends CommonBundle implements XmlUtils.WriteMapCallback {
+ private static final String TAG_PERSISTABLEMAP = "pbundle_as_map";
public static final PersistableBundle EMPTY;
static final Parcel EMPTY_PARCEL;
@@ -88,6 +96,38 @@ public final class PersistableBundle extends CommonBundle {
}
/**
+ * Constructs a PersistableBundle containing the mappings passed in.
+ *
+ * @param map a Map containing only those items that can be persisted.
+ * @throws IllegalArgumentException if any element of #map cannot be persisted.
+ */
+ private PersistableBundle(Map<String, Object> map) {
+ super();
+
+ // First stuff everything in.
+ putAll(map);
+
+ // Now verify each item throwing an exception if there is a violation.
+ Set<String> keys = map.keySet();
+ Iterator<String> iterator = keys.iterator();
+ while (iterator.hasNext()) {
+ String key = iterator.next();
+ Object value = map.get(key);
+ if (value instanceof Map) {
+ // Fix up any Maps by replacing them with PersistableBundles.
+ putPersistableBundle(key, new PersistableBundle((Map<String, Object>) value));
+ } else if (!(value instanceof Integer) && !(value instanceof Long) &&
+ !(value instanceof Double) && !(value instanceof String) &&
+ !(value instanceof int[]) && !(value instanceof long[]) &&
+ !(value instanceof double[]) && !(value instanceof String[]) &&
+ !(value instanceof PersistableBundle) && (value != null)) {
+ throw new IllegalArgumentException("Bad value in PersistableBundle key=" + key +
+ " value=" + value);
+ }
+ }
+ }
+
+ /**
* Make a PersistableBundle for a single key/value pair.
*
* @hide
@@ -206,6 +246,7 @@ public final class PersistableBundle extends CommonBundle {
*
* @param bundle a PersistableBundle
*/
+ @Override
public void putAll(PersistableBundle bundle) {
super.putAll(bundle);
}
@@ -323,6 +364,7 @@ public final class PersistableBundle extends CommonBundle {
* @param key a String, or null
* @param value a Bundle object, or null
*/
+ @Override
public void putPersistableBundle(String key, PersistableBundle value) {
super.putPersistableBundle(key, value);
}
@@ -539,6 +581,57 @@ public final class PersistableBundle extends CommonBundle {
super.readFromParcelInner(parcel);
}
+ /** @hide */
+ @Override
+ public void writeUnknownObject(Object v, String name, XmlSerializer out)
+ throws XmlPullParserException, IOException {
+ if (v instanceof PersistableBundle) {
+ out.startTag(null, TAG_PERSISTABLEMAP);
+ out.attribute(null, "name", name);
+ ((PersistableBundle) v).saveToXml(out);
+ out.endTag(null, TAG_PERSISTABLEMAP);
+ } else {
+ throw new XmlPullParserException("Unknown Object o=" + v);
+ }
+ }
+
+ /** @hide */
+ public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
+ unparcel();
+ XmlUtils.writeMapXml(mMap, out, this);
+ }
+
+ /** @hide */
+ static class MyReadMapCallback implements XmlUtils.ReadMapCallback {
+ @Override
+ public Object readThisUnknownObjectXml(XmlPullParser in, String tag)
+ throws XmlPullParserException, IOException {
+ if (TAG_PERSISTABLEMAP.equals(tag)) {
+ return restoreFromXml(in);
+ }
+ throw new XmlPullParserException("Unknown tag=" + tag);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public static PersistableBundle restoreFromXml(XmlPullParser in) throws IOException,
+ XmlPullParserException {
+ final int outerDepth = in.getDepth();
+ final String startTag = in.getName();
+ final String[] tagName = new String[1];
+ int event;
+ while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
+ (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+ if (event == XmlPullParser.START_TAG) {
+ return new PersistableBundle((Map<String, Object>)
+ XmlUtils.readThisMapXml(in, startTag, tagName, new MyReadMapCallback()));
+ }
+ }
+ return EMPTY;
+ }
+
@Override
synchronized public String toString() {
if (mParcelledData != null) {
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 5b59599..dca9921 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -220,28 +220,74 @@ public class XmlUtils {
* @see #readMapXml
*/
public static final void writeMapXml(Map val, String name, XmlSerializer out)
- throws XmlPullParserException, java.io.IOException
- {
+ throws XmlPullParserException, java.io.IOException {
+ writeMapXml(val, name, out, null);
+ }
+
+ /**
+ * Flatten a Map into an XmlSerializer. The map can later be read back
+ * with readThisMapXml().
+ *
+ * @param val The map to be flattened.
+ * @param name Name attribute to include with this list's tag, or null for
+ * none.
+ * @param out XmlSerializer to write the map into.
+ * @param callback Method to call when an Object type is not recognized.
+ *
+ * @see #writeMapXml(Map, OutputStream)
+ * @see #writeListXml
+ * @see #writeValueXml
+ * @see #readMapXml
+ *
+ * @hide
+ */
+ public static final void writeMapXml(Map val, String name, XmlSerializer out,
+ WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
+
if (val == null) {
out.startTag(null, "null");
out.endTag(null, "null");
return;
}
- Set s = val.entrySet();
- Iterator i = s.iterator();
-
out.startTag(null, "map");
if (name != null) {
out.attribute(null, "name", name);
}
+ writeMapXml(val, out, callback);
+
+ out.endTag(null, "map");
+ }
+
+ /**
+ * Flatten a Map into an XmlSerializer. The map can later be read back
+ * with readThisMapXml(). This method presumes that the start tag and
+ * name attribute have already been written and does not write an end tag.
+ *
+ * @param val The map to be flattened.
+ * @param out XmlSerializer to write the map into.
+ *
+ * @see #writeMapXml(Map, OutputStream)
+ * @see #writeListXml
+ * @see #writeValueXml
+ * @see #readMapXml
+ *
+ * @hide
+ */
+ public static final void writeMapXml(Map val, XmlSerializer out,
+ WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
+ if (val == null) {
+ return;
+ }
+
+ Set s = val.entrySet();
+ Iterator i = s.iterator();
+
while (i.hasNext()) {
Map.Entry e = (Map.Entry)i.next();
- writeValueXml(e.getValue(), (String)e.getKey(), out);
+ writeValueXml(e.getValue(), (String)e.getKey(), out, callback);
}
-
- out.endTag(null, "map");
}
/**
@@ -387,6 +433,123 @@ public class XmlUtils {
}
/**
+ * Flatten a long[] into an XmlSerializer. The list can later be read back
+ * with readThisLongArrayXml().
+ *
+ * @param val The long array to be flattened.
+ * @param name Name attribute to include with this array's tag, or null for
+ * none.
+ * @param out XmlSerializer to write the array into.
+ *
+ * @see #writeMapXml
+ * @see #writeValueXml
+ * @see #readThisIntArrayXml
+ */
+ public static final void writeLongArrayXml(long[] val, String name, XmlSerializer out)
+ throws XmlPullParserException, java.io.IOException {
+
+ if (val == null) {
+ out.startTag(null, "null");
+ out.endTag(null, "null");
+ return;
+ }
+
+ out.startTag(null, "long-array");
+ if (name != null) {
+ out.attribute(null, "name", name);
+ }
+
+ final int N = val.length;
+ out.attribute(null, "num", Integer.toString(N));
+
+ for (int i=0; i<N; i++) {
+ out.startTag(null, "item");
+ out.attribute(null, "value", Long.toString(val[i]));
+ out.endTag(null, "item");
+ }
+
+ out.endTag(null, "long-array");
+ }
+
+ /**
+ * Flatten a double[] into an XmlSerializer. The list can later be read back
+ * with readThisDoubleArrayXml().
+ *
+ * @param val The double array to be flattened.
+ * @param name Name attribute to include with this array's tag, or null for
+ * none.
+ * @param out XmlSerializer to write the array into.
+ *
+ * @see #writeMapXml
+ * @see #writeValueXml
+ * @see #readThisIntArrayXml
+ */
+ public static final void writeDoubleArrayXml(double[] val, String name, XmlSerializer out)
+ throws XmlPullParserException, java.io.IOException {
+
+ if (val == null) {
+ out.startTag(null, "null");
+ out.endTag(null, "null");
+ return;
+ }
+
+ out.startTag(null, "double-array");
+ if (name != null) {
+ out.attribute(null, "name", name);
+ }
+
+ final int N = val.length;
+ out.attribute(null, "num", Integer.toString(N));
+
+ for (int i=0; i<N; i++) {
+ out.startTag(null, "item");
+ out.attribute(null, "value", Double.toString(val[i]));
+ out.endTag(null, "item");
+ }
+
+ out.endTag(null, "double-array");
+ }
+
+ /**
+ * Flatten a String[] into an XmlSerializer. The list can later be read back
+ * with readThisStringArrayXml().
+ *
+ * @param val The long array to be flattened.
+ * @param name Name attribute to include with this array's tag, or null for
+ * none.
+ * @param out XmlSerializer to write the array into.
+ *
+ * @see #writeMapXml
+ * @see #writeValueXml
+ * @see #readThisIntArrayXml
+ */
+ public static final void writeStringArrayXml(String[] val, String name, XmlSerializer out)
+ throws XmlPullParserException, java.io.IOException {
+
+ if (val == null) {
+ out.startTag(null, "null");
+ out.endTag(null, "null");
+ return;
+ }
+
+ out.startTag(null, "string-array");
+ if (name != null) {
+ out.attribute(null, "name", name);
+ }
+
+ final int N = val.length;
+ out.attribute(null, "num", Integer.toString(N));
+
+ for (int i=0; i<N; i++) {
+ out.startTag(null, "item");
+ out.attribute(null, "value", val[i]);
+ out.endTag(null, "item");
+ }
+
+ out.endTag(null, "string-array");
+ }
+
+ /**
* Flatten an object's value into an XmlSerializer. The value can later
* be read back with readThisValueXml().
*
@@ -403,8 +566,29 @@ public class XmlUtils {
* @see #readValueXml
*/
public static final void writeValueXml(Object v, String name, XmlSerializer out)
- throws XmlPullParserException, java.io.IOException
- {
+ throws XmlPullParserException, java.io.IOException {
+ writeValueXml(v, name, out, null);
+ }
+
+ /**
+ * Flatten an object's value into an XmlSerializer. The value can later
+ * be read back with readThisValueXml().
+ *
+ * Currently supported value types are: null, String, Integer, Long,
+ * Float, Double Boolean, Map, List.
+ *
+ * @param v The object to be flattened.
+ * @param name Name attribute to include with this value's tag, or null
+ * for none.
+ * @param out XmlSerializer to write the object into.
+ * @param callback Handler for Object types not recognized.
+ *
+ * @see #writeMapXml
+ * @see #writeListXml
+ * @see #readValueXml
+ */
+ private static final void writeValueXml(Object v, String name, XmlSerializer out,
+ WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
String typeStr;
if (v == null) {
out.startTag(null, "null");
@@ -437,14 +621,23 @@ public class XmlUtils {
} else if (v instanceof int[]) {
writeIntArrayXml((int[])v, name, out);
return;
+ } else if (v instanceof long[]) {
+ writeLongArrayXml((long[])v, name, out);
+ return;
+ } else if (v instanceof double[]) {
+ writeDoubleArrayXml((double[])v, name, out);
+ return;
+ } else if (v instanceof String[]) {
+ writeStringArrayXml((String[])v, name, out);
+ return;
} else if (v instanceof Map) {
writeMapXml((Map)v, name, out);
return;
} else if (v instanceof List) {
- writeListXml((List)v, name, out);
+ writeListXml((List) v, name, out);
return;
} else if (v instanceof Set) {
- writeSetXml((Set)v, name, out);
+ writeSetXml((Set) v, name, out);
return;
} else if (v instanceof CharSequence) {
// XXX This is to allow us to at least write something if
@@ -457,6 +650,9 @@ public class XmlUtils {
out.text(v.toString());
out.endTag(null, "string");
return;
+ } else if (callback != null) {
+ callback.writeUnknownObject(v, name, out);
+ return;
} else {
throw new RuntimeException("writeValueXml: unable to write value " + v);
}
@@ -550,14 +746,35 @@ public class XmlUtils {
* @see #readMapXml
*/
public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
- String[] name) throws XmlPullParserException, java.io.IOException
+ String[] name) throws XmlPullParserException, java.io.IOException {
+ return readThisMapXml(parser, endTag, name, null);
+ }
+
+ /**
+ * Read a HashMap object from an XmlPullParser. The XML data could
+ * previously have been generated by writeMapXml(). The XmlPullParser
+ * must be positioned <em>after</em> the tag that begins the map.
+ *
+ * @param parser The XmlPullParser from which to read the map data.
+ * @param endTag Name of the tag that will end the map, usually "map".
+ * @param name An array of one string, used to return the name attribute
+ * of the map's tag.
+ *
+ * @return HashMap The newly generated map.
+ *
+ * @see #readMapXml
+ * @hide
+ */
+ public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
+ String[] name, ReadMapCallback callback)
+ throws XmlPullParserException, java.io.IOException
{
HashMap<String, Object> map = new HashMap<String, Object>();
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name);
+ Object val = readThisValueXml(parser, name, callback);
map.put(name[0], val);
} else if (eventType == parser.END_TAG) {
if (parser.getName().equals(endTag)) {
@@ -587,15 +804,34 @@ public class XmlUtils {
*
* @see #readListXml
*/
- public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name)
- throws XmlPullParserException, java.io.IOException
- {
+ public static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
+ String[] name) throws XmlPullParserException, java.io.IOException {
+ return readThisListXml(parser, endTag, name, null);
+ }
+
+ /**
+ * Read an ArrayList object from an XmlPullParser. The XML data could
+ * previously have been generated by writeListXml(). The XmlPullParser
+ * must be positioned <em>after</em> the tag that begins the list.
+ *
+ * @param parser The XmlPullParser from which to read the list data.
+ * @param endTag Name of the tag that will end the list, usually "list".
+ * @param name An array of one string, used to return the name attribute
+ * of the list's tag.
+ *
+ * @return HashMap The newly generated list.
+ *
+ * @see #readListXml
+ */
+ private static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
+ String[] name, ReadMapCallback callback)
+ throws XmlPullParserException, java.io.IOException {
ArrayList list = new ArrayList();
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name);
+ Object val = readThisValueXml(parser, name, callback);
list.add(val);
//System.out.println("Adding to list: " + val);
} else if (eventType == parser.END_TAG) {
@@ -611,7 +847,29 @@ public class XmlUtils {
throw new XmlPullParserException(
"Document ended before " + endTag + " end tag");
}
-
+
+ /**
+ * Read a HashSet object from an XmlPullParser. The XML data could previously
+ * have been generated by writeSetXml(). The XmlPullParser must be positioned
+ * <em>after</em> the tag that begins the set.
+ *
+ * @param parser The XmlPullParser from which to read the set data.
+ * @param endTag Name of the tag that will end the set, usually "set".
+ * @param name An array of one string, used to return the name attribute
+ * of the set's tag.
+ *
+ * @return HashSet The newly generated set.
+ *
+ * @throws XmlPullParserException
+ * @throws java.io.IOException
+ *
+ * @see #readSetXml
+ */
+ public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
+ throws XmlPullParserException, java.io.IOException {
+ return readThisSetXml(parser, endTag, name, null);
+ }
+
/**
* Read a HashSet object from an XmlPullParser. The XML data could previously
* have been generated by writeSetXml(). The XmlPullParser must be positioned
@@ -628,15 +886,16 @@ public class XmlUtils {
* @throws java.io.IOException
*
* @see #readSetXml
+ * @hide
*/
- public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
- throws XmlPullParserException, java.io.IOException {
+ private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name,
+ ReadMapCallback callback) throws XmlPullParserException, java.io.IOException {
HashSet set = new HashSet();
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name);
+ Object val = readThisValueXml(parser, name, callback);
set.add(val);
//System.out.println("Adding to set: " + val);
} else if (eventType == parser.END_TAG) {
@@ -681,6 +940,7 @@ public class XmlUtils {
throw new XmlPullParserException(
"Not a number in num attribute in byte-array");
}
+ parser.next();
int[] array = new int[num];
int i = 0;
@@ -722,6 +982,187 @@ public class XmlUtils {
}
/**
+ * Read a long[] object from an XmlPullParser. The XML data could
+ * previously have been generated by writeLongArrayXml(). The XmlPullParser
+ * must be positioned <em>after</em> the tag that begins the list.
+ *
+ * @param parser The XmlPullParser from which to read the list data.
+ * @param endTag Name of the tag that will end the list, usually "list".
+ * @param name An array of one string, used to return the name attribute
+ * of the list's tag.
+ *
+ * @return Returns a newly generated long[].
+ *
+ * @see #readListXml
+ */
+ public static final long[] readThisLongArrayXml(XmlPullParser parser,
+ String endTag, String[] name)
+ throws XmlPullParserException, java.io.IOException {
+
+ int num;
+ try {
+ num = Integer.parseInt(parser.getAttributeValue(null, "num"));
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need num attribute in long-array");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in num attribute in long-array");
+ }
+ parser.next();
+
+ long[] array = new long[num];
+ int i = 0;
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == parser.START_TAG) {
+ if (parser.getName().equals("item")) {
+ try {
+ array[i] = Long.parseLong(parser.getAttributeValue(null, "value"));
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need value attribute in item");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in value attribute in item");
+ }
+ } else {
+ throw new XmlPullParserException("Expected item tag at: " + parser.getName());
+ }
+ } else if (eventType == parser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return array;
+ } else if (parser.getName().equals("item")) {
+ i++;
+ } else {
+ throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
+ parser.getName());
+ }
+ }
+ eventType = parser.next();
+ } while (eventType != parser.END_DOCUMENT);
+
+ throw new XmlPullParserException("Document ended before " + endTag + " end tag");
+ }
+
+ /**
+ * Read a double[] object from an XmlPullParser. The XML data could
+ * previously have been generated by writeDoubleArrayXml(). The XmlPullParser
+ * must be positioned <em>after</em> the tag that begins the list.
+ *
+ * @param parser The XmlPullParser from which to read the list data.
+ * @param endTag Name of the tag that will end the list, usually "double-array".
+ * @param name An array of one string, used to return the name attribute
+ * of the list's tag.
+ *
+ * @return Returns a newly generated double[].
+ *
+ * @see #readListXml
+ */
+ public static final double[] readThisDoubleArrayXml(XmlPullParser parser, String endTag,
+ String[] name) throws XmlPullParserException, java.io.IOException {
+
+ int num;
+ try {
+ num = Integer.parseInt(parser.getAttributeValue(null, "num"));
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need num attribute in double-array");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in num attribute in double-array");
+ }
+ parser.next();
+
+ double[] array = new double[num];
+ int i = 0;
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == parser.START_TAG) {
+ if (parser.getName().equals("item")) {
+ try {
+ array[i] = Double.parseDouble(parser.getAttributeValue(null, "value"));
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need value attribute in item");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in value attribute in item");
+ }
+ } else {
+ throw new XmlPullParserException("Expected item tag at: " + parser.getName());
+ }
+ } else if (eventType == parser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return array;
+ } else if (parser.getName().equals("item")) {
+ i++;
+ } else {
+ throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
+ parser.getName());
+ }
+ }
+ eventType = parser.next();
+ } while (eventType != parser.END_DOCUMENT);
+
+ throw new XmlPullParserException("Document ended before " + endTag + " end tag");
+ }
+
+ /**
+ * Read a String[] object from an XmlPullParser. The XML data could
+ * previously have been generated by writeStringArrayXml(). The XmlPullParser
+ * must be positioned <em>after</em> the tag that begins the list.
+ *
+ * @param parser The XmlPullParser from which to read the list data.
+ * @param endTag Name of the tag that will end the list, usually "string-array".
+ * @param name An array of one string, used to return the name attribute
+ * of the list's tag.
+ *
+ * @return Returns a newly generated String[].
+ *
+ * @see #readListXml
+ */
+ public static final String[] readThisStringArrayXml(XmlPullParser parser, String endTag,
+ String[] name) throws XmlPullParserException, java.io.IOException {
+
+ int num;
+ try {
+ num = Integer.parseInt(parser.getAttributeValue(null, "num"));
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need num attribute in string-array");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in num attribute in string-array");
+ }
+ parser.next();
+
+ String[] array = new String[num];
+ int i = 0;
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == parser.START_TAG) {
+ if (parser.getName().equals("item")) {
+ try {
+ array[i] = parser.getAttributeValue(null, "value");
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need value attribute in item");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in value attribute in item");
+ }
+ } else {
+ throw new XmlPullParserException("Expected item tag at: " + parser.getName());
+ }
+ } else if (eventType == parser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return array;
+ } else if (parser.getName().equals("item")) {
+ i++;
+ } else {
+ throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
+ parser.getName());
+ }
+ }
+ eventType = parser.next();
+ } while (eventType != parser.END_DOCUMENT);
+
+ throw new XmlPullParserException("Document ended before " + endTag + " end tag");
+ }
+
+ /**
* Read a flattened object from an XmlPullParser. The XML data could
* previously have been written with writeMapXml(), writeListXml(), or
* writeValueXml(). The XmlPullParser must be positioned <em>at</em> the
@@ -743,7 +1184,7 @@ public class XmlUtils {
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- return readThisValueXml(parser, name);
+ return readThisValueXml(parser, name, null);
} else if (eventType == parser.END_TAG) {
throw new XmlPullParserException(
"Unexpected end tag at: " + parser.getName());
@@ -758,9 +1199,8 @@ public class XmlUtils {
"Unexpected end of document");
}
- private static final Object readThisValueXml(XmlPullParser parser, String[] name)
- throws XmlPullParserException, java.io.IOException
- {
+ private static final Object readThisValueXml(XmlPullParser parser, String[] name,
+ ReadMapCallback callback) throws XmlPullParserException, java.io.IOException {
final String valueName = parser.getAttributeValue(null, "name");
final String tagName = parser.getName();
@@ -794,11 +1234,25 @@ public class XmlUtils {
} else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) {
// all work already done by readThisPrimitiveValueXml
} else if (tagName.equals("int-array")) {
- parser.next();
res = readThisIntArrayXml(parser, "int-array", name);
name[0] = valueName;
//System.out.println("Returning value for " + valueName + ": " + res);
return res;
+ } else if (tagName.equals("long-array")) {
+ res = readThisLongArrayXml(parser, "long-array", name);
+ name[0] = valueName;
+ //System.out.println("Returning value for " + valueName + ": " + res);
+ return res;
+ } else if (tagName.equals("double-array")) {
+ res = readThisDoubleArrayXml(parser, "double-array", name);
+ name[0] = valueName;
+ //System.out.println("Returning value for " + valueName + ": " + res);
+ return res;
+ } else if (tagName.equals("string-array")) {
+ res = readThisStringArrayXml(parser, "string-array", name);
+ name[0] = valueName;
+ //System.out.println("Returning value for " + valueName + ": " + res);
+ return res;
} else if (tagName.equals("map")) {
parser.next();
res = readThisMapXml(parser, "map", name);
@@ -817,9 +1271,12 @@ public class XmlUtils {
name[0] = valueName;
//System.out.println("Returning value for " + valueName + ": " + res);
return res;
+ } else if (callback != null) {
+ res = callback.readThisUnknownObjectXml(parser, tagName);
+ name[0] = valueName;
+ return res;
} else {
- throw new XmlPullParserException(
- "Unknown tag: " + tagName);
+ throw new XmlPullParserException("Unknown tag: " + tagName);
}
// Skip through to end tag.
@@ -967,4 +1424,39 @@ public class XmlUtils {
throws IOException {
out.attribute(null, name, Boolean.toString(value));
}
+
+ /** @hide */
+ public interface WriteMapCallback {
+ /**
+ * Called from writeMapXml when an Object type is not recognized. The implementer
+ * must write out the entire element including start and end tags.
+ *
+ * @param v The object to be written out
+ * @param name The mapping key for v. Must be written into the "name" attribute of the
+ * start tag.
+ * @param out The XML output stream.
+ * @throws XmlPullParserException on unrecognized Object type.
+ * @throws IOException on XmlSerializer serialization errors.
+ * @hide
+ */
+ public void writeUnknownObject(Object v, String name, XmlSerializer out)
+ throws XmlPullParserException, IOException;
+ }
+
+ /** @hide */
+ public interface ReadMapCallback {
+ /**
+ * Called from readThisMapXml when a START_TAG is not recognized. The input stream
+ * is positioned within the start tag so that attributes can be read using in.getAttribute.
+ *
+ * @param in the XML input stream
+ * @param tag the START_TAG that was not recognized.
+ * @return the Object parsed from the stream which will be put into the map.
+ * @throws XmlPullParserException if the START_TAG is not recognized.
+ * @throws IOException on XmlPullParser serialization errors.
+ * @hide
+ */
+ public Object readThisUnknownObjectXml(XmlPullParser in, String tag)
+ throws XmlPullParserException, IOException;
+ }
}