From a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 11 Mar 2015 15:16:13 -0700 Subject: More work on collecting assist data. Optimize parceling of AssistData (which is now renamed to AssistStructure) by pooling duplicated class name strings. Change text associated with a view node to a CharSequence, so styling information comes along. Include global text attributes -- size, colors, etc. Introduce a new AssistContent structure, which allows us to propagate information about the intent and data the activity is looking at. This further allows us to propagate permission grants, so the assistant can dig in to that data. The default implementation propagates the base intent of an activity, so if for example you bring up the assistant while doing a share the assistant itself has the same information and access that was given to the share activity (so it could for example share it in another way if it wanted to). Did some optimization of loading PersistableBundle from xml, to avoid duplicating hash maps and such. Changed how we dispatch ACTION_ASSIST to no longer include the more detailed AssistStructure (and new AssistContent) data when launching; now the example code that intercepts that needs to be sure to ask for assist data when it starts its session. This is more like it will finally be, and allows us to get to the UI more quickly. Change-Id: I88420a55761bf48d34ce3013e81bd96a0e087637 --- core/java/android/os/BaseBundle.java | 3 +- core/java/android/os/Bundle.java | 23 +++++++++ core/java/android/os/PersistableBundle.java | 40 ++++++++------- core/java/android/os/PooledStringReader.java | 50 ++++++++++++++++++ core/java/android/os/PooledStringWriter.java | 76 ++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 20 deletions(-) create mode 100644 core/java/android/os/PooledStringReader.java create mode 100644 core/java/android/os/PooledStringWriter.java (limited to 'core/java/android/os') diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java index 7f8c95b..c373308 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -22,7 +22,6 @@ import android.util.Log; import java.io.Serializable; import java.util.ArrayList; -import java.util.Map; import java.util.Set; /** @@ -309,7 +308,7 @@ public class BaseBundle { * * @param map a Map */ - void putAll(Map map) { + void putAll(ArrayMap map) { unparcel(); mMap.putAll(map); } diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index c20024a..5e9b8c1 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -252,6 +252,29 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } /** + * Filter values in Bundle to only basic types. + * @hide + */ + public void filterValues() { + unparcel(); + if (mMap != null) { + for (int i = mMap.size() - 1; i >= 0; i--) { + Object value = mMap.valueAt(i); + if (PersistableBundle.isValidType(value)) { + continue; + } + if (value instanceof Bundle) { + ((Bundle)value).filterValues(); + } + if (value.getClass().getName().startsWith("android.")) { + continue; + } + mMap.removeAt(i); + } + } + } + + /** * Inserts a byte value into the mapping of this Bundle, replacing * any existing value for the given key. * diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java index a467c87..ea180b2 100644 --- a/core/java/android/os/PersistableBundle.java +++ b/core/java/android/os/PersistableBundle.java @@ -45,6 +45,16 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL; } + /** @hide */ + public static boolean isValidType(Object value) { + return (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) || + (value instanceof Boolean) || (value instanceof boolean[]); + } + /** * Constructs a new, empty PersistableBundle. */ @@ -78,29 +88,22 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa * @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 map) { + private PersistableBundle(ArrayMap map) { super(); // First stuff everything in. putAll(map); // Now verify each item throwing an exception if there is a violation. - Set keys = map.keySet(); - Iterator iterator = keys.iterator(); - while (iterator.hasNext()) { - String key = iterator.next(); - Object value = map.get(key); - if (value instanceof Map) { + final int N = mMap.size(); + for (int i=0; i) 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) && - !(value instanceof Boolean) && !(value instanceof boolean[])) { - throw new IllegalArgumentException("Bad value in PersistableBundle key=" + key + - " value=" + value); + mMap.setValueAt(i, new PersistableBundle((ArrayMap) value)); + } else if (!isValidType(value)) { + throw new IllegalArgumentException("Bad value in PersistableBundle key=" + + mMap.keyAt(i) + " value=" + value); } } } @@ -242,8 +245,9 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) { if (event == XmlPullParser.START_TAG) { - return new PersistableBundle((Map) - XmlUtils.readThisMapXml(in, startTag, tagName, new MyReadMapCallback())); + return new PersistableBundle((ArrayMap) + XmlUtils.readThisArrayMapXml(in, startTag, tagName, + new MyReadMapCallback())); } } return EMPTY; diff --git a/core/java/android/os/PooledStringReader.java b/core/java/android/os/PooledStringReader.java new file mode 100644 index 0000000..7795957 --- /dev/null +++ b/core/java/android/os/PooledStringReader.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** + * Helper class for reading pooling strings from a Parcel. It must be used + * in conjunction with {@link android.os.PooledStringWriter}. This really needs + * to be pushed in to Parcel itself, but doing that is... complicated. + * @hide + */ +public class PooledStringReader { + private final Parcel mIn; + + /** + * The pool of strings we have collected so far. + */ + private final String[] mPool; + + public PooledStringReader(Parcel in) { + mIn = in; + final int size = in.readInt(); + mPool = new String[size]; + } + + public String readString() { + int idx = mIn.readInt(); + if (idx >= 0) { + return mPool[idx]; + } else { + idx = (-idx) - 1; + String str = mIn.readString(); + mPool[idx] = str; + return str; + } + } +} diff --git a/core/java/android/os/PooledStringWriter.java b/core/java/android/os/PooledStringWriter.java new file mode 100644 index 0000000..eac297d --- /dev/null +++ b/core/java/android/os/PooledStringWriter.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import java.util.HashMap; + +/** + * Helper class for writing pooled strings into a Parcel. It must be used + * in conjunction with {@link android.os.PooledStringReader}. This really needs + * to be pushed in to Parcel itself, but doing that is... complicated. + * @hide + */ +public class PooledStringWriter { + private final Parcel mOut; + + /** + * Book-keeping for writing pooled string objects, mapping strings we have + * written so far to their index in the pool. We deliberately use HashMap + * here since performance is critical, we expect to be doing lots of adds to + * it, and it is only a temporary object so its overall memory footprint is + * not a signifciant issue. + */ + private final HashMap mPool; + + /** + * Book-keeping for writing pooling string objects, indicating where we + * started writing the pool, which is where we need to ultimately store + * how many strings are in the pool. + */ + private int mStart; + + /** + * Next available index in the pool. + */ + private int mNext; + + public PooledStringWriter(Parcel out) { + mOut = out; + mPool = new HashMap<>(); + mStart = out.dataPosition(); + out.writeInt(0); // reserve space for final pool size. + } + + public void writeString(String str) { + final Integer cur = mPool.get(str); + if (cur != null) { + mOut.writeInt(cur); + } else { + mPool.put(str, mNext); + mOut.writeInt(-(mNext+1)); + mOut.writeString(str); + mNext++; + } + } + + public void finish() { + final int pos = mOut.dataPosition(); + mOut.setDataPosition(mStart); + mOut.writeInt(mNext); + mOut.setDataPosition(pos); + } +} -- cgit v1.1